Merge "Document the limitations of Linkify addresses"
diff --git a/Android.mk b/Android.mk
index a20798d..669efc7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -174,9 +174,6 @@
core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \
core/java/android/hardware/usb/IUsbManager.aidl \
- core/java/android/midi/IMidiDeviceServer.aidl \
- core/java/android/midi/IMidiListener.aidl \
- core/java/android/midi/IMidiManager.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/net/IEthernetManager.aidl \
core/java/android/net/IEthernetServiceListener.aidl \
@@ -335,7 +332,10 @@
media/java/android/media/IRemoteVolumeObserver.aidl \
media/java/android/media/IRingtonePlayer.aidl \
media/java/android/media/IVolumeController.aidl \
- media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl \
+ media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl \
+ media/java/android/media/midi/IMidiDeviceServer.aidl \
+ media/java/android/media/midi/IMidiListener.aidl \
+ media/java/android/media/midi/IMidiManager.aidl \
media/java/android/media/projection/IMediaProjection.aidl \
media/java/android/media/projection/IMediaProjectionCallback.aidl \
media/java/android/media/projection/IMediaProjectionManager.aidl \
@@ -614,7 +614,10 @@
# TODO: deal with com/google/android/googleapps
packages_to_document := \
android \
- javax/microedition/khronos
+ javax/microedition/khronos \
+ org/apache/http/conn \
+ org/apache/http/params
+
# Search through the base framework dirs for these packages.
# The result will be relative to frameworks/base.
@@ -635,7 +638,6 @@
include external/junit/Common.mk
non_base_dirs := \
- ../../external/apache-http/src/org/apache/http \
../opt/telephony/src/java/android/provider \
../opt/telephony/src/java/android/telephony \
../opt/telephony/src/java/android/telephony/gsm \
@@ -1024,13 +1026,8 @@
# Build ext.jar
# ============================================================
-# NOTICE notes for non-obvious sections
-# apache-http - covered by the Apache Commons section.
-
-
ext_dirs := \
../../external/nist-sip/java \
- ../../external/apache-http/src \
../../external/tagsoup/src \
ext_src_files := $(call all-java-files-under,$(ext_dirs))
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c35f332..c812b6a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -228,6 +228,11 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/SystemUI_intermediates/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/Keyguard_intermediates/)
$(call add-clean-step, rm -f $(OUT_DIR)/target/product/*/system/framework/android.policy.jar)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/inputflinger $(PRODUCT_OUT)/symbols/system/bin/inputflinger)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libinputflingerhost.so $(PRODUCT_OUT)/system/lib64/libinputflingerhost.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/lib/libinputflingerhost.so $(PRODUCT_OUT)/symbols/system/lib64/libinputflingerhost.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/libinputflingerhost.so $(PRODUCT_OUT)/obj_arm/lib/libinputflingerhost.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libinputflingerhost_intermediates $(PRODUCT_OUT)/obj_arm/SHARED_LIBRARIES/libinputflingerhost_intermediates)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index cd4f73a..6749453 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -886,6 +886,7 @@
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
+ field public static final int numbersInnerTextColor = 16843999; // 0x10104df
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
field public static final int numbersTextColor = 16843937; // 0x10104a1
field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -1709,8 +1710,10 @@
field public static final int message = 16908299; // 0x102000b
field public static final int navigationBarBackground = 16908336; // 0x1020030
field public static final int paste = 16908322; // 0x1020022
+ field public static final int pasteAsPlainText = 16908339; // 0x1020033
field public static final int primary = 16908300; // 0x102000c
field public static final int progress = 16908301; // 0x102000d
+ field public static final int redo = 16908338; // 0x1020032
field public static final int secondaryProgress = 16908303; // 0x102000f
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
@@ -1727,6 +1730,7 @@
field public static final int text2 = 16908309; // 0x1020015
field public static final int title = 16908310; // 0x1020016
field public static final int toggle = 16908311; // 0x1020017
+ field public static final int undo = 16908337; // 0x1020031
field public static final int widget_frame = 16908312; // 0x1020018
}
@@ -2086,6 +2090,21 @@
field public static final int Theme_Light_Panel = 16973914; // 0x103005a
field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
field public static final int Theme_Material = 16974372; // 0x1030224
+ field public static final int Theme_Material_DayNight = 16974548; // 0x10302d4
+ field public static final int Theme_Material_DayNight_DarkActionBar = 16974549; // 0x10302d5
+ field public static final int Theme_Material_DayNight_Dialog = 16974550; // 0x10302d6
+ field public static final int Theme_Material_DayNight_DialogWhenLarge = 16974556; // 0x10302dc
+ field public static final int Theme_Material_DayNight_DialogWhenLarge_NoActionBar = 16974557; // 0x10302dd
+ field public static final int Theme_Material_DayNight_Dialog_Alert = 16974551; // 0x10302d7
+ field public static final int Theme_Material_DayNight_Dialog_MinWidth = 16974552; // 0x10302d8
+ field public static final int Theme_Material_DayNight_Dialog_NoActionBar = 16974553; // 0x10302d9
+ field public static final int Theme_Material_DayNight_Dialog_NoActionBar_MinWidth = 16974554; // 0x10302da
+ field public static final int Theme_Material_DayNight_Dialog_Presentation = 16974555; // 0x10302db
+ field public static final int Theme_Material_DayNight_NoActionBar = 16974558; // 0x10302de
+ field public static final int Theme_Material_DayNight_NoActionBar_Fullscreen = 16974559; // 0x10302df
+ field public static final int Theme_Material_DayNight_NoActionBar_Overscan = 16974560; // 0x10302e0
+ field public static final int Theme_Material_DayNight_NoActionBar_TranslucentDecor = 16974561; // 0x10302e1
+ field public static final int Theme_Material_DayNight_Panel = 16974562; // 0x10302e2
field public static final int Theme_Material_Dialog = 16974373; // 0x1030225
field public static final int Theme_Material_DialogWhenLarge = 16974379; // 0x103022b
field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974380; // 0x103022c
@@ -2105,6 +2124,7 @@
field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974396; // 0x103023c
field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974397; // 0x103023d
field public static final int Theme_Material_Light_Dialog_Presentation = 16974398; // 0x103023e
+ field public static final int Theme_Material_Light_LightStatusBar = 16974563; // 0x10302e3
field public static final int Theme_Material_Light_NoActionBar = 16974401; // 0x1030241
field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974402; // 0x1030242
field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974403; // 0x1030243
@@ -3681,6 +3701,7 @@
}
public class ActivityOptions {
+ method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
@@ -3922,6 +3943,7 @@
public final class AssistData implements android.os.Parcelable {
method public int describeContents();
+ method public android.content.ComponentName getActivityComponent();
method public static android.app.AssistData getAssistData(android.os.Bundle);
method public void getWindowAt(int, android.app.AssistData.ViewNode);
method public int getWindowCount();
@@ -5387,6 +5409,7 @@
ctor public DeviceAdminReceiver();
method public android.app.admin.DevicePolicyManager getManager(android.content.Context);
method public android.content.ComponentName getWho(android.content.Context);
+ method public java.lang.String onChoosePrivateKeyAlias(android.content.Context, android.content.Intent, int, java.lang.String, int, java.lang.String, java.lang.String);
method public java.lang.CharSequence onDisableRequested(android.content.Context, android.content.Intent);
method public void onDisabled(android.content.Context, android.content.Intent);
method public void onEnabled(android.content.Context, android.content.Intent);
@@ -5455,7 +5478,6 @@
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
- method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5504,13 +5526,13 @@
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
- method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
@@ -11774,15 +11796,8 @@
method public final void setTileModeY(android.graphics.Shader.TileMode);
}
- public class ClipDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class ClipDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public ClipDrawable(android.graphics.drawable.Drawable, int, int);
- method public void draw(android.graphics.Canvas);
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
field public static final int HORIZONTAL = 1; // 0x1
field public static final int VERTICAL = 2; // 0x2
}
@@ -11824,8 +11839,10 @@
method public android.graphics.Rect getDirtyBounds();
method public boolean getDither();
method public boolean getFilterBitmap();
+ method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
+ method public int getLayoutDirection();
method public final int getLevel();
method public int getMinimumHeight();
method public int getMinimumWidth();
@@ -11843,6 +11860,7 @@
method public void jumpToCurrentState();
method public android.graphics.drawable.Drawable mutate();
method protected void onBoundsChange(android.graphics.Rect);
+ method public boolean onLayoutDirectionChange(int);
method protected boolean onLevelChange(int);
method protected boolean onStateChange(int[]);
method public static int resolveOpacity(int, int);
@@ -11859,6 +11877,7 @@
method public void setFilterBitmap(boolean);
method public void setHotspot(float, float);
method public void setHotspotBounds(int, int, int, int);
+ method public final boolean setLayoutDirection(int);
method public final boolean setLevel(int);
method public boolean setState(int[]);
method public void setTint(int);
@@ -11923,6 +11942,19 @@
method public final void setVariablePadding(boolean);
}
+ public abstract class DrawableWrapper extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public DrawableWrapper(android.graphics.drawable.Drawable);
+ method public void draw(android.graphics.Canvas);
+ method public android.graphics.drawable.Drawable getDrawable();
+ method public int getOpacity();
+ method public void invalidateDrawable(android.graphics.drawable.Drawable);
+ method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+ method public void setAlpha(int);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDrawable(android.graphics.drawable.Drawable);
+ method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+ }
+
public class GradientDrawable extends android.graphics.drawable.Drawable {
ctor public GradientDrawable();
ctor public GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation, int[]);
@@ -11970,27 +12002,27 @@
enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TR_BL;
}
- public class InsetDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class InsetDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public InsetDrawable(android.graphics.drawable.Drawable, int);
ctor public InsetDrawable(android.graphics.drawable.Drawable, int, int, int, int);
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
public class LayerDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
ctor public LayerDrawable(android.graphics.drawable.Drawable[]);
+ method public int addLayer(android.graphics.drawable.Drawable);
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable findDrawableByLayerId(int);
+ method public int findIndexByLayerId(int);
method public android.graphics.drawable.Drawable getDrawable(int);
method public int getId(int);
method public int getLayerGravity(int);
method public int getLayerHeight(int);
+ method public int getLayerInsetBottom(int);
+ method public int getLayerInsetEnd(int);
+ method public int getLayerInsetLeft(int);
+ method public int getLayerInsetRight(int);
+ method public int getLayerInsetStart(int);
+ method public int getLayerInsetTop(int);
method public int getLayerWidth(int);
method public int getNumberOfLayers();
method public int getOpacity();
@@ -11999,12 +12031,21 @@
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
method public void setAlpha(int);
method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDrawable(int, android.graphics.drawable.Drawable);
method public boolean setDrawableByLayerId(int, android.graphics.drawable.Drawable);
method public void setId(int, int);
method public void setLayerGravity(int, int);
+ method public void setLayerHeight(int, int);
method public void setLayerInset(int, int, int, int, int);
+ method public void setLayerInsetBottom(int, int);
+ method public void setLayerInsetEnd(int, int);
+ method public void setLayerInsetLeft(int, int);
method public void setLayerInsetRelative(int, int, int, int, int);
+ method public void setLayerInsetRight(int, int);
+ method public void setLayerInsetStart(int, int);
+ method public void setLayerInsetTop(int, int);
method public void setLayerSize(int, int, int);
+ method public void setLayerWidth(int, int);
method public void setOpacity(int);
method public void setPaddingMode(int);
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
@@ -12051,44 +12092,30 @@
public class RippleDrawable extends android.graphics.drawable.LayerDrawable {
ctor public RippleDrawable(android.content.res.ColorStateList, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+ method public int getRadius();
method public void setColor(android.content.res.ColorStateList);
+ method public void setRadius(int);
+ field public static final int RADIUS_AUTO = -1; // 0xffffffff
}
- public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class RotateDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public RotateDrawable();
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
method public float getFromDegrees();
- method public int getOpacity();
method public float getPivotX();
method public float getPivotY();
method public float getToDegrees();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
method public boolean isPivotXRelative();
method public boolean isPivotYRelative();
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void setDrawable(android.graphics.drawable.Drawable);
method public void setFromDegrees(float);
method public void setPivotX(float);
method public void setPivotXRelative(boolean);
method public void setPivotY(float);
method public void setPivotYRelative(boolean);
method public void setToDegrees(float);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
- public class ScaleDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class ScaleDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public ScaleDrawable(android.graphics.drawable.Drawable, int, float, float);
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
public class ShapeDrawable extends android.graphics.drawable.Drawable {
@@ -17906,30 +17933,6 @@
package android.net.http {
- public final deprecated class AndroidHttpClient implements org.apache.http.client.HttpClient {
- method public void close();
- method public void disableCurlLogging();
- method public void enableCurlLogging(java.lang.String, int);
- method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public static org.apache.http.entity.AbstractHttpEntity getCompressedEntity(byte[], android.content.ContentResolver) throws java.io.IOException;
- method public org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public static long getMinGzipSize(android.content.ContentResolver);
- method public org.apache.http.params.HttpParams getParams();
- method public static java.io.InputStream getUngzippedContent(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static void modifyRequestToAcceptGzipResponse(org.apache.http.HttpRequest);
- method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context);
- method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String);
- method public static long parseDate(java.lang.String);
- field public static long DEFAULT_SYNC_MIN_GZIP_BYTES;
- }
-
public final class HttpResponseCache extends java.net.ResponseCache implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public void delete() throws java.io.IOException;
@@ -27317,6 +27320,7 @@
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
+ method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String, java.lang.String);
method public static android.content.Intent createInstallIntent();
method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
@@ -27536,6 +27540,7 @@
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
+ field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
}
@@ -27650,9 +27655,10 @@
method public android.os.IBinder onBind(android.content.Intent);
method public void onReady();
method public void onShutdown();
- method public void startSession(android.os.Bundle);
+ method public void startSession(android.os.Bundle, int);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+ field public static final int START_WITH_ASSIST = 1; // 0x1
}
public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
@@ -27670,10 +27676,11 @@
method public void onCompleteVoice(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
- method public void onCreate(android.os.Bundle);
+ method public void onCreate(android.os.Bundle, int);
method public android.view.View onCreateContentView();
method public void onDestroy();
method public boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
+ method public void onHandleAssist(android.os.Bundle);
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
@@ -28740,6 +28747,7 @@
method public boolean isInCall();
method public void showInCallScreen(boolean);
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
@@ -31789,6 +31797,7 @@
method public android.transition.Transition addTarget(java.lang.String);
method public android.transition.Transition addTarget(java.lang.Class);
method public android.transition.Transition addTarget(android.view.View);
+ method protected boolean areValuesChanged(android.transition.TransitionValues, android.transition.TransitionValues);
method public boolean canRemoveViews();
method public abstract void captureEndValues(android.transition.TransitionValues);
method public abstract void captureStartValues(android.transition.TransitionValues);
@@ -32043,6 +32052,7 @@
method public boolean equals(android.util.DisplayMetrics);
method public void setTo(android.util.DisplayMetrics);
method public void setToDefaults();
+ field public static final int DENSITY_280 = 280; // 0x118
field public static final int DENSITY_400 = 400; // 0x190
field public static final int DENSITY_560 = 560; // 0x230
field public static final int DENSITY_DEFAULT = 160; // 0xa0
@@ -37785,6 +37795,7 @@
ctor public CompoundButton(android.content.Context, android.util.AttributeSet);
ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int);
ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int, int);
+ method public android.graphics.drawable.Drawable getButtonDrawable();
method public android.content.res.ColorStateList getButtonTintList();
method public android.graphics.PorterDuff.Mode getButtonTintMode();
method public boolean isChecked();
@@ -54865,1105 +54876,13 @@
}
-package org.apache.commons.logging {
-
- public abstract deprecated interface Log {
- method public abstract void debug(java.lang.Object);
- method public abstract void debug(java.lang.Object, java.lang.Throwable);
- method public abstract void error(java.lang.Object);
- method public abstract void error(java.lang.Object, java.lang.Throwable);
- method public abstract void fatal(java.lang.Object);
- method public abstract void fatal(java.lang.Object, java.lang.Throwable);
- method public abstract void info(java.lang.Object);
- method public abstract void info(java.lang.Object, java.lang.Throwable);
- method public abstract boolean isDebugEnabled();
- method public abstract boolean isErrorEnabled();
- method public abstract boolean isFatalEnabled();
- method public abstract boolean isInfoEnabled();
- method public abstract boolean isTraceEnabled();
- method public abstract boolean isWarnEnabled();
- method public abstract void trace(java.lang.Object);
- method public abstract void trace(java.lang.Object, java.lang.Throwable);
- method public abstract void warn(java.lang.Object);
- method public abstract void warn(java.lang.Object, java.lang.Throwable);
- }
-
-}
-
-package org.apache.http {
-
- public deprecated class ConnectionClosedException extends java.io.IOException {
- ctor public ConnectionClosedException(java.lang.String);
- }
-
- public abstract deprecated interface ConnectionReuseStrategy {
- method public abstract boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface FormattedHeader implements org.apache.http.Header {
- method public abstract org.apache.http.util.CharArrayBuffer getBuffer();
- method public abstract int getValuePos();
- }
-
- public abstract deprecated interface Header {
- method public abstract org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getValue();
- }
-
- public abstract deprecated interface HeaderElement {
- method public abstract java.lang.String getName();
- method public abstract org.apache.http.NameValuePair getParameter(int);
- method public abstract org.apache.http.NameValuePair getParameterByName(java.lang.String);
- method public abstract int getParameterCount();
- method public abstract org.apache.http.NameValuePair[] getParameters();
- method public abstract java.lang.String getValue();
- }
-
- public abstract deprecated interface HeaderElementIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract org.apache.http.HeaderElement nextElement();
- }
-
- public abstract deprecated interface HeaderIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract org.apache.http.Header nextHeader();
- }
-
- public abstract deprecated interface HttpClientConnection implements org.apache.http.HttpConnection {
- method public abstract void flush() throws java.io.IOException;
- method public abstract boolean isResponseAvailable(int) throws java.io.IOException;
- method public abstract void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpConnection {
- method public abstract void close() throws java.io.IOException;
- method public abstract org.apache.http.HttpConnectionMetrics getMetrics();
- method public abstract int getSocketTimeout();
- method public abstract boolean isOpen();
- method public abstract boolean isStale();
- method public abstract void setSocketTimeout(int);
- method public abstract void shutdown() throws java.io.IOException;
- }
-
- public abstract deprecated interface HttpConnectionMetrics {
- method public abstract java.lang.Object getMetric(java.lang.String);
- method public abstract long getReceivedBytesCount();
- method public abstract long getRequestCount();
- method public abstract long getResponseCount();
- method public abstract long getSentBytesCount();
- method public abstract void reset();
- }
-
- public abstract deprecated interface HttpEntity {
- method public abstract void consumeContent() throws java.io.IOException;
- method public abstract java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
- method public abstract org.apache.http.Header getContentEncoding();
- method public abstract long getContentLength();
- method public abstract org.apache.http.Header getContentType();
- method public abstract boolean isChunked();
- method public abstract boolean isRepeatable();
- method public abstract boolean isStreaming();
- method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public abstract deprecated interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest {
- method public abstract boolean expectContinue();
- method public abstract org.apache.http.HttpEntity getEntity();
- method public abstract void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class HttpException extends java.lang.Exception {
- ctor public HttpException();
- ctor public HttpException(java.lang.String);
- ctor public HttpException(java.lang.String, java.lang.Throwable);
- }
-
- public final deprecated class HttpHost implements java.lang.Cloneable {
- ctor public HttpHost(java.lang.String, int, java.lang.String);
- ctor public HttpHost(java.lang.String, int);
- ctor public HttpHost(java.lang.String);
- ctor public HttpHost(org.apache.http.HttpHost);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getHostName();
- method public int getPort();
- method public java.lang.String getSchemeName();
- method public java.lang.String toHostString();
- method public java.lang.String toURI();
- field public static final java.lang.String DEFAULT_SCHEME_NAME = "http";
- field protected final java.lang.String hostname;
- field protected final java.lang.String lcHostname;
- field protected final int port;
- field protected final java.lang.String schemeName;
- }
-
- public abstract deprecated interface HttpInetConnection implements org.apache.http.HttpConnection {
- method public abstract java.net.InetAddress getLocalAddress();
- method public abstract int getLocalPort();
- method public abstract java.net.InetAddress getRemoteAddress();
- method public abstract int getRemotePort();
- }
-
- public abstract deprecated interface HttpMessage {
- method public abstract void addHeader(org.apache.http.Header);
- method public abstract void addHeader(java.lang.String, java.lang.String);
- method public abstract boolean containsHeader(java.lang.String);
- method public abstract org.apache.http.Header[] getAllHeaders();
- method public abstract org.apache.http.Header getFirstHeader(java.lang.String);
- method public abstract org.apache.http.Header[] getHeaders(java.lang.String);
- method public abstract org.apache.http.Header getLastHeader(java.lang.String);
- method public abstract org.apache.http.params.HttpParams getParams();
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract org.apache.http.HeaderIterator headerIterator();
- method public abstract org.apache.http.HeaderIterator headerIterator(java.lang.String);
- method public abstract void removeHeader(org.apache.http.Header);
- method public abstract void removeHeaders(java.lang.String);
- method public abstract void setHeader(org.apache.http.Header);
- method public abstract void setHeader(java.lang.String, java.lang.String);
- method public abstract void setHeaders(org.apache.http.Header[]);
- method public abstract void setParams(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated interface HttpRequest implements org.apache.http.HttpMessage {
- method public abstract org.apache.http.RequestLine getRequestLine();
- }
-
- public abstract deprecated interface HttpRequestFactory {
- method public abstract org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
- method public abstract org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
- }
-
- public abstract deprecated interface HttpRequestInterceptor {
- method public abstract void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpResponse implements org.apache.http.HttpMessage {
- method public abstract org.apache.http.HttpEntity getEntity();
- method public abstract java.util.Locale getLocale();
- method public abstract org.apache.http.StatusLine getStatusLine();
- method public abstract void setEntity(org.apache.http.HttpEntity);
- method public abstract void setLocale(java.util.Locale);
- method public abstract void setReasonPhrase(java.lang.String) throws java.lang.IllegalStateException;
- method public abstract void setStatusCode(int) throws java.lang.IllegalStateException;
- method public abstract void setStatusLine(org.apache.http.StatusLine);
- method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int);
- method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- }
-
- public abstract deprecated interface HttpResponseFactory {
- method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
- method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface HttpResponseInterceptor {
- method public abstract void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpServerConnection implements org.apache.http.HttpConnection {
- method public abstract void flush() throws java.io.IOException;
- method public abstract void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpStatus {
- field public static final int SC_ACCEPTED = 202; // 0xca
- field public static final int SC_BAD_GATEWAY = 502; // 0x1f6
- field public static final int SC_BAD_REQUEST = 400; // 0x190
- field public static final int SC_CONFLICT = 409; // 0x199
- field public static final int SC_CONTINUE = 100; // 0x64
- field public static final int SC_CREATED = 201; // 0xc9
- field public static final int SC_EXPECTATION_FAILED = 417; // 0x1a1
- field public static final int SC_FAILED_DEPENDENCY = 424; // 0x1a8
- field public static final int SC_FORBIDDEN = 403; // 0x193
- field public static final int SC_GATEWAY_TIMEOUT = 504; // 0x1f8
- field public static final int SC_GONE = 410; // 0x19a
- field public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; // 0x1f9
- field public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; // 0x1a3
- field public static final int SC_INSUFFICIENT_STORAGE = 507; // 0x1fb
- field public static final int SC_INTERNAL_SERVER_ERROR = 500; // 0x1f4
- field public static final int SC_LENGTH_REQUIRED = 411; // 0x19b
- field public static final int SC_LOCKED = 423; // 0x1a7
- field public static final int SC_METHOD_FAILURE = 420; // 0x1a4
- field public static final int SC_METHOD_NOT_ALLOWED = 405; // 0x195
- field public static final int SC_MOVED_PERMANENTLY = 301; // 0x12d
- field public static final int SC_MOVED_TEMPORARILY = 302; // 0x12e
- field public static final int SC_MULTIPLE_CHOICES = 300; // 0x12c
- field public static final int SC_MULTI_STATUS = 207; // 0xcf
- field public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; // 0xcb
- field public static final int SC_NOT_ACCEPTABLE = 406; // 0x196
- field public static final int SC_NOT_FOUND = 404; // 0x194
- field public static final int SC_NOT_IMPLEMENTED = 501; // 0x1f5
- field public static final int SC_NOT_MODIFIED = 304; // 0x130
- field public static final int SC_NO_CONTENT = 204; // 0xcc
- field public static final int SC_OK = 200; // 0xc8
- field public static final int SC_PARTIAL_CONTENT = 206; // 0xce
- field public static final int SC_PAYMENT_REQUIRED = 402; // 0x192
- field public static final int SC_PRECONDITION_FAILED = 412; // 0x19c
- field public static final int SC_PROCESSING = 102; // 0x66
- field public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; // 0x197
- field public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; // 0x1a0
- field public static final int SC_REQUEST_TIMEOUT = 408; // 0x198
- field public static final int SC_REQUEST_TOO_LONG = 413; // 0x19d
- field public static final int SC_REQUEST_URI_TOO_LONG = 414; // 0x19e
- field public static final int SC_RESET_CONTENT = 205; // 0xcd
- field public static final int SC_SEE_OTHER = 303; // 0x12f
- field public static final int SC_SERVICE_UNAVAILABLE = 503; // 0x1f7
- field public static final int SC_SWITCHING_PROTOCOLS = 101; // 0x65
- field public static final int SC_TEMPORARY_REDIRECT = 307; // 0x133
- field public static final int SC_UNAUTHORIZED = 401; // 0x191
- field public static final int SC_UNPROCESSABLE_ENTITY = 422; // 0x1a6
- field public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; // 0x19f
- field public static final int SC_USE_PROXY = 305; // 0x131
- }
-
- public final deprecated class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable {
- ctor public HttpVersion(int, int);
- field public static final java.lang.String HTTP = "HTTP";
- field public static final org.apache.http.HttpVersion HTTP_0_9;
- field public static final org.apache.http.HttpVersion HTTP_1_0;
- field public static final org.apache.http.HttpVersion HTTP_1_1;
- }
-
- public deprecated class MalformedChunkCodingException extends java.io.IOException {
- ctor public MalformedChunkCodingException();
- ctor public MalformedChunkCodingException(java.lang.String);
- }
-
- public deprecated class MethodNotSupportedException extends org.apache.http.HttpException {
- ctor public MethodNotSupportedException(java.lang.String);
- ctor public MethodNotSupportedException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface NameValuePair {
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getValue();
- }
-
- public deprecated class NoHttpResponseException extends java.io.IOException {
- ctor public NoHttpResponseException(java.lang.String);
- }
-
- public deprecated class ParseException extends java.lang.RuntimeException {
- ctor public ParseException();
- ctor public ParseException(java.lang.String);
- }
-
- public deprecated class ProtocolException extends org.apache.http.HttpException {
- ctor public ProtocolException();
- ctor public ProtocolException(java.lang.String);
- ctor public ProtocolException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class ProtocolVersion implements java.lang.Cloneable java.io.Serializable {
- ctor public ProtocolVersion(java.lang.String, int, int);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public int compareToVersion(org.apache.http.ProtocolVersion);
- method public final boolean equals(java.lang.Object);
- method public org.apache.http.ProtocolVersion forVersion(int, int);
- method public final int getMajor();
- method public final int getMinor();
- method public final java.lang.String getProtocol();
- method public final boolean greaterEquals(org.apache.http.ProtocolVersion);
- method public final int hashCode();
- method public boolean isComparable(org.apache.http.ProtocolVersion);
- method public final boolean lessEquals(org.apache.http.ProtocolVersion);
- field protected final int major;
- field protected final int minor;
- field protected final java.lang.String protocol;
- }
-
- public abstract deprecated interface ReasonPhraseCatalog {
- method public abstract java.lang.String getReason(int, java.util.Locale);
- }
-
- public abstract deprecated interface RequestLine {
- method public abstract java.lang.String getMethod();
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract java.lang.String getUri();
- }
-
- public abstract deprecated interface StatusLine {
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract java.lang.String getReasonPhrase();
- method public abstract int getStatusCode();
- }
-
- public abstract deprecated interface TokenIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract java.lang.String nextToken();
- }
-
- public deprecated class UnsupportedHttpVersionException extends org.apache.http.ProtocolException {
- ctor public UnsupportedHttpVersionException();
- ctor public UnsupportedHttpVersionException(java.lang.String);
- }
-
-}
-
-package org.apache.http.auth {
-
- public final deprecated class AUTH {
- field public static final java.lang.String PROXY_AUTH = "Proxy-Authenticate";
- field public static final java.lang.String PROXY_AUTH_RESP = "Proxy-Authorization";
- field public static final java.lang.String WWW_AUTH = "WWW-Authenticate";
- field public static final java.lang.String WWW_AUTH_RESP = "Authorization";
- }
-
- public abstract deprecated interface AuthScheme {
- method public abstract org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public abstract java.lang.String getParameter(java.lang.String);
- method public abstract java.lang.String getRealm();
- method public abstract java.lang.String getSchemeName();
- method public abstract boolean isComplete();
- method public abstract boolean isConnectionBased();
- method public abstract void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public abstract deprecated interface AuthSchemeFactory {
- method public abstract org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public final deprecated class AuthSchemeRegistry {
- ctor public AuthSchemeRegistry();
- method public synchronized org.apache.http.auth.AuthScheme getAuthScheme(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
- method public synchronized java.util.List<java.lang.String> getSchemeNames();
- method public synchronized void register(java.lang.String, org.apache.http.auth.AuthSchemeFactory);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.auth.AuthSchemeFactory>);
- method public synchronized void unregister(java.lang.String);
- }
-
- public deprecated class AuthScope {
- ctor public AuthScope(java.lang.String, int, java.lang.String, java.lang.String);
- ctor public AuthScope(java.lang.String, int, java.lang.String);
- ctor public AuthScope(java.lang.String, int);
- ctor public AuthScope(org.apache.http.auth.AuthScope);
- method public java.lang.String getHost();
- method public int getPort();
- method public java.lang.String getRealm();
- method public java.lang.String getScheme();
- method public int match(org.apache.http.auth.AuthScope);
- field public static final org.apache.http.auth.AuthScope ANY;
- field public static final java.lang.String ANY_HOST;
- field public static final int ANY_PORT = -1; // 0xffffffff
- field public static final java.lang.String ANY_REALM;
- field public static final java.lang.String ANY_SCHEME;
- }
-
- public deprecated class AuthState {
- ctor public AuthState();
- method public org.apache.http.auth.AuthScheme getAuthScheme();
- method public org.apache.http.auth.AuthScope getAuthScope();
- method public org.apache.http.auth.Credentials getCredentials();
- method public void invalidate();
- method public boolean isValid();
- method public void setAuthScheme(org.apache.http.auth.AuthScheme);
- method public void setAuthScope(org.apache.http.auth.AuthScope);
- method public void setCredentials(org.apache.http.auth.Credentials);
- }
-
- public deprecated class AuthenticationException extends org.apache.http.ProtocolException {
- ctor public AuthenticationException();
- ctor public AuthenticationException(java.lang.String);
- ctor public AuthenticationException(java.lang.String, java.lang.Throwable);
- }
-
- public final deprecated class BasicUserPrincipal implements java.security.Principal {
- ctor public BasicUserPrincipal(java.lang.String);
- method public java.lang.String getName();
- }
-
- public abstract deprecated interface Credentials {
- method public abstract java.lang.String getPassword();
- method public abstract java.security.Principal getUserPrincipal();
- }
-
- public deprecated class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException {
- ctor public InvalidCredentialsException();
- ctor public InvalidCredentialsException(java.lang.String);
- ctor public InvalidCredentialsException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class MalformedChallengeException extends org.apache.http.ProtocolException {
- ctor public MalformedChallengeException();
- ctor public MalformedChallengeException(java.lang.String);
- ctor public MalformedChallengeException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class NTCredentials implements org.apache.http.auth.Credentials {
- ctor public NTCredentials(java.lang.String);
- ctor public NTCredentials(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- method public java.lang.String getDomain();
- method public java.lang.String getPassword();
- method public java.lang.String getUserName();
- method public java.security.Principal getUserPrincipal();
- method public java.lang.String getWorkstation();
- }
-
- public deprecated class NTUserPrincipal implements java.security.Principal {
- ctor public NTUserPrincipal(java.lang.String, java.lang.String);
- method public java.lang.String getDomain();
- method public java.lang.String getName();
- method public java.lang.String getUsername();
- }
-
- public deprecated class UsernamePasswordCredentials implements org.apache.http.auth.Credentials {
- ctor public UsernamePasswordCredentials(java.lang.String);
- ctor public UsernamePasswordCredentials(java.lang.String, java.lang.String);
- method public java.lang.String getPassword();
- method public java.lang.String getUserName();
- method public java.security.Principal getUserPrincipal();
- }
-
-}
-
-package org.apache.http.auth.params {
-
- public abstract deprecated interface AuthPNames {
- field public static final java.lang.String CREDENTIAL_CHARSET = "http.auth.credential-charset";
- }
-
- public deprecated class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public AuthParamBean(org.apache.http.params.HttpParams);
- method public void setCredentialCharset(java.lang.String);
- }
-
- public final deprecated class AuthParams {
- method public static java.lang.String getCredentialCharset(org.apache.http.params.HttpParams);
- method public static void setCredentialCharset(org.apache.http.params.HttpParams, java.lang.String);
- }
-
-}
-
-package org.apache.http.client {
-
- public abstract deprecated interface AuthenticationHandler {
- method public abstract java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public abstract boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- method public abstract org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
- }
-
- public deprecated class CircularRedirectException extends org.apache.http.client.RedirectException {
- ctor public CircularRedirectException();
- ctor public CircularRedirectException(java.lang.String);
- ctor public CircularRedirectException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class ClientProtocolException extends java.io.IOException {
- ctor public ClientProtocolException();
- ctor public ClientProtocolException(java.lang.String);
- ctor public ClientProtocolException(java.lang.Throwable);
- ctor public ClientProtocolException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface CookieStore {
- method public abstract void addCookie(org.apache.http.cookie.Cookie);
- method public abstract void clear();
- method public abstract boolean clearExpired(java.util.Date);
- method public abstract java.util.List<org.apache.http.cookie.Cookie> getCookies();
- }
-
- public abstract deprecated interface CredentialsProvider {
- method public abstract void clear();
- method public abstract org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
- method public abstract void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
- }
-
- public abstract deprecated interface HttpClient {
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public abstract org.apache.http.params.HttpParams getParams();
- }
-
- public abstract deprecated interface HttpRequestRetryHandler {
- method public abstract boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class HttpResponseException extends org.apache.http.client.ClientProtocolException {
- ctor public HttpResponseException(int, java.lang.String);
- method public int getStatusCode();
- }
-
- public deprecated class NonRepeatableRequestException extends org.apache.http.ProtocolException {
- ctor public NonRepeatableRequestException();
- ctor public NonRepeatableRequestException(java.lang.String);
- }
-
- public deprecated class RedirectException extends org.apache.http.ProtocolException {
- ctor public RedirectException();
- ctor public RedirectException(java.lang.String);
- ctor public RedirectException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface RedirectHandler {
- method public abstract java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
- method public abstract boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface RequestDirector {
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface ResponseHandler {
- method public abstract T handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- }
-
- public abstract deprecated interface UserTokenHandler {
- method public abstract java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
- }
-
-}
-
-package org.apache.http.client.entity {
-
- public deprecated class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity {
- ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String) throws java.io.UnsupportedEncodingException;
- ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>) throws java.io.UnsupportedEncodingException;
- }
-
-}
-
-package org.apache.http.client.methods {
-
- public abstract deprecated interface AbortableHttpRequest {
- method public abstract void abort();
- method public abstract void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
- method public abstract void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
- }
-
- public deprecated class HttpDelete extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpDelete();
- ctor public HttpDelete(java.net.URI);
- ctor public HttpDelete(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "DELETE";
- }
-
- public abstract deprecated class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public HttpEntityEnclosingRequestBase();
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class HttpGet extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpGet();
- ctor public HttpGet(java.net.URI);
- ctor public HttpGet(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "GET";
- }
-
- public deprecated class HttpHead extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpHead();
- ctor public HttpHead(java.net.URI);
- ctor public HttpHead(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "HEAD";
- }
-
- public deprecated class HttpOptions extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpOptions();
- ctor public HttpOptions(java.net.URI);
- ctor public HttpOptions(java.lang.String);
- method public java.util.Set<java.lang.String> getAllowedMethods(org.apache.http.HttpResponse);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "OPTIONS";
- }
-
- public deprecated class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
- ctor public HttpPost();
- ctor public HttpPost(java.net.URI);
- ctor public HttpPost(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "POST";
- }
-
- public deprecated class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
- ctor public HttpPut();
- ctor public HttpPut(java.net.URI);
- ctor public HttpPut(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "PUT";
- }
-
- public abstract deprecated class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest {
- ctor public HttpRequestBase();
- method public void abort();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public abstract java.lang.String getMethod();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- method public java.net.URI getURI();
- method public boolean isAborted();
- method public void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
- method public void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
- method public void setURI(java.net.URI);
- }
-
- public deprecated class HttpTrace extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpTrace();
- ctor public HttpTrace(java.net.URI);
- ctor public HttpTrace(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "TRACE";
- }
-
- public abstract deprecated interface HttpUriRequest implements org.apache.http.HttpRequest {
- method public abstract void abort() throws java.lang.UnsupportedOperationException;
- method public abstract java.lang.String getMethod();
- method public abstract java.net.URI getURI();
- method public abstract boolean isAborted();
- }
-
-}
-
-package org.apache.http.client.params {
-
- public abstract deprecated interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames {
- }
-
- public final deprecated class AuthPolicy {
- field public static final java.lang.String BASIC = "Basic";
- field public static final java.lang.String DIGEST = "Digest";
- field public static final java.lang.String NTLM = "NTLM";
- }
-
- public abstract deprecated interface ClientPNames {
- field public static final java.lang.String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
- field public static final java.lang.String CONNECTION_MANAGER_FACTORY = "http.connection-manager.factory-object";
- field public static final java.lang.String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
- field public static final java.lang.String COOKIE_POLICY = "http.protocol.cookie-policy";
- field public static final java.lang.String DEFAULT_HEADERS = "http.default-headers";
- field public static final java.lang.String DEFAULT_HOST = "http.default-host";
- field public static final java.lang.String HANDLE_AUTHENTICATION = "http.protocol.handle-authentication";
- field public static final java.lang.String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
- field public static final java.lang.String MAX_REDIRECTS = "http.protocol.max-redirects";
- field public static final java.lang.String REJECT_RELATIVE_REDIRECT = "http.protocol.reject-relative-redirect";
- field public static final java.lang.String VIRTUAL_HOST = "http.virtual-host";
- }
-
- public deprecated class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ClientParamBean(org.apache.http.params.HttpParams);
- method public void setAllowCircularRedirects(boolean);
- method public void setConnectionManagerFactory(org.apache.http.conn.ClientConnectionManagerFactory);
- method public void setConnectionManagerFactoryClassName(java.lang.String);
- method public void setCookiePolicy(java.lang.String);
- method public void setDefaultHeaders(java.util.Collection<org.apache.http.Header>);
- method public void setDefaultHost(org.apache.http.HttpHost);
- method public void setHandleAuthentication(boolean);
- method public void setHandleRedirects(boolean);
- method public void setMaxRedirects(int);
- method public void setRejectRelativeRedirect(boolean);
- method public void setVirtualHost(org.apache.http.HttpHost);
- }
-
- public final deprecated class CookiePolicy {
- field public static final java.lang.String BEST_MATCH = "best-match";
- field public static final java.lang.String BROWSER_COMPATIBILITY = "compatibility";
- field public static final java.lang.String NETSCAPE = "netscape";
- field public static final java.lang.String RFC_2109 = "rfc2109";
- field public static final java.lang.String RFC_2965 = "rfc2965";
- }
-
- public deprecated class HttpClientParams {
- method public static java.lang.String getCookiePolicy(org.apache.http.params.HttpParams);
- method public static boolean isAuthenticating(org.apache.http.params.HttpParams);
- method public static boolean isRedirecting(org.apache.http.params.HttpParams);
- method public static void setAuthenticating(org.apache.http.params.HttpParams, boolean);
- method public static void setCookiePolicy(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setRedirecting(org.apache.http.params.HttpParams, boolean);
- }
-
-}
-
-package org.apache.http.client.protocol {
-
- public abstract deprecated interface ClientContext {
- field public static final java.lang.String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
- field public static final java.lang.String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
- field public static final java.lang.String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
- field public static final java.lang.String COOKIE_ORIGIN = "http.cookie-origin";
- field public static final java.lang.String COOKIE_SPEC = "http.cookie-spec";
- field public static final java.lang.String COOKIE_STORE = "http.cookie-store";
- field public static final java.lang.String CREDS_PROVIDER = "http.auth.credentials-provider";
- field public static final java.lang.String PROXY_AUTH_STATE = "http.auth.proxy-scope";
- field public static final java.lang.String TARGET_AUTH_STATE = "http.auth.target-scope";
- field public static final java.lang.String USER_TOKEN = "http.user-token";
- }
-
- public deprecated class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext {
- ctor public ClientContextConfigurer(org.apache.http.protocol.HttpContext);
- method public void setAuthSchemePref(java.util.List<java.lang.String>);
- method public void setAuthSchemeRegistry(org.apache.http.auth.AuthSchemeRegistry);
- method public void setCookieSpecRegistry(org.apache.http.cookie.CookieSpecRegistry);
- method public void setCookieStore(org.apache.http.client.CookieStore);
- method public void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
- }
-
- public deprecated class RequestAddCookies implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestAddCookies();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestDefaultHeaders();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestProxyAuthentication();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestTargetAuthentication();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseProcessCookies();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
-}
-
-package org.apache.http.client.utils {
-
- public deprecated class CloneUtils {
- method public static java.lang.Object clone(java.lang.Object) throws java.lang.CloneNotSupportedException;
- }
-
- public deprecated class URIUtils {
- method public static java.net.URI createURI(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
- method public static java.net.URI resolve(java.net.URI, java.lang.String);
- method public static java.net.URI resolve(java.net.URI, java.net.URI);
- method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost, boolean) throws java.net.URISyntaxException;
- method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost) throws java.net.URISyntaxException;
- }
-
- public deprecated class URLEncodedUtils {
- ctor public URLEncodedUtils();
- method public static java.lang.String format(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String);
- method public static boolean isEncoded(org.apache.http.HttpEntity);
- method public static java.util.List<org.apache.http.NameValuePair> parse(java.net.URI, java.lang.String);
- method public static java.util.List<org.apache.http.NameValuePair> parse(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static void parse(java.util.List<org.apache.http.NameValuePair>, java.util.Scanner, java.lang.String);
- field public static final java.lang.String CONTENT_TYPE = "application/x-www-form-urlencoded";
- }
-
-}
-
package org.apache.http.conn {
- public deprecated class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher {
- ctor public BasicEofSensorWatcher(org.apache.http.conn.ManagedClientConnection, boolean);
- method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- field protected boolean attemptReuse;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- }
-
- public deprecated class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher {
- ctor public BasicManagedEntity(org.apache.http.HttpEntity, org.apache.http.conn.ManagedClientConnection, boolean);
- method public void abortConnection() throws java.io.IOException;
- method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public void releaseConnection() throws java.io.IOException;
- method protected void releaseManagedConnection() throws java.io.IOException;
- method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- field protected final boolean attemptReuse;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- }
-
- public abstract deprecated interface ClientConnectionManager {
- method public abstract void closeExpiredConnections();
- method public abstract void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method public abstract org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public abstract void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public abstract org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public abstract void shutdown();
- }
-
- public abstract deprecated interface ClientConnectionManagerFactory {
- method public abstract org.apache.http.conn.ClientConnectionManager newInstance(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- }
-
- public abstract deprecated interface ClientConnectionOperator {
- method public abstract org.apache.http.conn.OperatedClientConnection createConnection();
- method public abstract void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public abstract deprecated interface ClientConnectionRequest {
- method public abstract void abortRequest();
- method public abstract org.apache.http.conn.ManagedClientConnection getConnection(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- }
-
public deprecated class ConnectTimeoutException extends java.io.InterruptedIOException {
ctor public ConnectTimeoutException();
ctor public ConnectTimeoutException(java.lang.String);
}
- public abstract deprecated interface ConnectionKeepAliveStrategy {
- method public abstract long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException {
- ctor public ConnectionPoolTimeoutException();
- ctor public ConnectionPoolTimeoutException(java.lang.String);
- }
-
- public abstract deprecated interface ConnectionReleaseTrigger {
- method public abstract void abortConnection() throws java.io.IOException;
- method public abstract void releaseConnection() throws java.io.IOException;
- }
-
- public deprecated class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger {
- ctor public EofSensorInputStream(java.io.InputStream, org.apache.http.conn.EofSensorWatcher);
- method public void abortConnection() throws java.io.IOException;
- method protected void checkAbort() throws java.io.IOException;
- method protected void checkClose() throws java.io.IOException;
- method protected void checkEOF(int) throws java.io.IOException;
- method protected boolean isReadAllowed() throws java.io.IOException;
- method public int read() throws java.io.IOException;
- method public void releaseConnection() throws java.io.IOException;
- field protected java.io.InputStream wrappedStream;
- }
-
- public abstract deprecated interface EofSensorWatcher {
- method public abstract boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public abstract boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public abstract boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- }
-
- public deprecated class HttpHostConnectException extends java.net.ConnectException {
- ctor public HttpHostConnectException(org.apache.http.HttpHost, java.net.ConnectException);
- method public org.apache.http.HttpHost getHost();
- }
-
- public abstract deprecated interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
- method public abstract org.apache.http.conn.routing.HttpRoute getRoute();
- method public abstract javax.net.ssl.SSLSession getSSLSession();
- method public abstract java.lang.Object getState();
- method public abstract boolean isMarkedReusable();
- method public abstract boolean isSecure();
- method public abstract void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void markReusable();
- method public abstract void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void setIdleDuration(long, java.util.concurrent.TimeUnit);
- method public abstract void setState(java.lang.Object);
- method public abstract void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void unmarkReusable();
- }
-
- public final deprecated class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
- method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.Socket createSocket();
- method public static org.apache.http.conn.MultihomePlainSocketFactory getSocketFactory();
- method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
- }
-
- public abstract deprecated interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
- method public abstract java.net.Socket getSocket();
- method public abstract org.apache.http.HttpHost getTargetHost();
- method public abstract boolean isSecure();
- method public abstract void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
- method public abstract void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.conn.params {
-
- public abstract deprecated interface ConnConnectionPNames {
- field public static final java.lang.String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage";
- }
-
- public deprecated class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnConnectionParamBean(org.apache.http.params.HttpParams);
- method public void setMaxStatusLineGarbage(int);
- }
-
- public abstract deprecated interface ConnManagerPNames {
- field public static final java.lang.String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route";
- field public static final java.lang.String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total";
- field public static final java.lang.String TIMEOUT = "http.conn-manager.timeout";
- }
-
- public deprecated class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnManagerParamBean(org.apache.http.params.HttpParams);
- method public void setConnectionsPerRoute(org.apache.http.conn.params.ConnPerRouteBean);
- method public void setMaxTotalConnections(int);
- method public void setTimeout(long);
- }
-
- public final deprecated class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames {
- ctor public ConnManagerParams();
- method public static org.apache.http.conn.params.ConnPerRoute getMaxConnectionsPerRoute(org.apache.http.params.HttpParams);
- method public static int getMaxTotalConnections(org.apache.http.params.HttpParams);
- method public static long getTimeout(org.apache.http.params.HttpParams);
- method public static void setMaxConnectionsPerRoute(org.apache.http.params.HttpParams, org.apache.http.conn.params.ConnPerRoute);
- method public static void setMaxTotalConnections(org.apache.http.params.HttpParams, int);
- method public static void setTimeout(org.apache.http.params.HttpParams, long);
- field public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; // 0x14
- }
-
- public abstract deprecated interface ConnPerRoute {
- method public abstract int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
- }
-
- public final deprecated class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute {
- ctor public ConnPerRouteBean(int);
- ctor public ConnPerRouteBean();
- method public int getDefaultMax();
- method public int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
- method public void setDefaultMaxPerRoute(int);
- method public void setMaxForRoute(org.apache.http.conn.routing.HttpRoute, int);
- method public void setMaxForRoutes(java.util.Map<org.apache.http.conn.routing.HttpRoute, java.lang.Integer>);
- field public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // 0x2
- }
-
- public abstract deprecated interface ConnRoutePNames {
- field public static final java.lang.String DEFAULT_PROXY = "http.route.default-proxy";
- field public static final java.lang.String FORCED_ROUTE = "http.route.forced-route";
- field public static final java.lang.String LOCAL_ADDRESS = "http.route.local-address";
- }
-
- public deprecated class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnRouteParamBean(org.apache.http.params.HttpParams);
- method public void setDefaultProxy(org.apache.http.HttpHost);
- method public void setForcedRoute(org.apache.http.conn.routing.HttpRoute);
- method public void setLocalAddress(java.net.InetAddress);
- }
-
- public deprecated class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames {
- method public static org.apache.http.HttpHost getDefaultProxy(org.apache.http.params.HttpParams);
- method public static org.apache.http.conn.routing.HttpRoute getForcedRoute(org.apache.http.params.HttpParams);
- method public static java.net.InetAddress getLocalAddress(org.apache.http.params.HttpParams);
- method public static void setDefaultProxy(org.apache.http.params.HttpParams, org.apache.http.HttpHost);
- method public static void setForcedRoute(org.apache.http.params.HttpParams, org.apache.http.conn.routing.HttpRoute);
- method public static void setLocalAddress(org.apache.http.params.HttpParams, java.net.InetAddress);
- field public static final org.apache.http.HttpHost NO_HOST;
- field public static final org.apache.http.conn.routing.HttpRoute NO_ROUTE;
- }
-
-}
-
-package org.apache.http.conn.routing {
-
- public deprecated class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector {
- ctor public BasicRouteDirector();
- method protected int directStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- method protected int firstStep(org.apache.http.conn.routing.RouteInfo);
- method public int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- method protected int proxiedStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- }
-
- public final deprecated class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost[], boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, boolean);
- ctor public HttpRoute(org.apache.http.HttpHost);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public final boolean equals(java.lang.Object);
- method public final int getHopCount();
- method public final org.apache.http.HttpHost getHopTarget(int);
- method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public final java.net.InetAddress getLocalAddress();
- method public final org.apache.http.HttpHost getProxyHost();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public final int hashCode();
- method public final boolean isLayered();
- method public final boolean isSecure();
- method public final boolean isTunnelled();
- method public final java.lang.String toString();
- }
-
- public abstract deprecated interface HttpRouteDirector {
- method public abstract int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- field public static final int COMPLETE = 0; // 0x0
- field public static final int CONNECT_PROXY = 2; // 0x2
- field public static final int CONNECT_TARGET = 1; // 0x1
- field public static final int LAYER_PROTOCOL = 5; // 0x5
- field public static final int TUNNEL_PROXY = 4; // 0x4
- field public static final int TUNNEL_TARGET = 3; // 0x3
- field public static final int UNREACHABLE = -1; // 0xffffffff
- }
-
- public abstract deprecated interface HttpRoutePlanner {
- method public abstract org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- }
-
- public abstract deprecated interface RouteInfo {
- method public abstract int getHopCount();
- method public abstract org.apache.http.HttpHost getHopTarget(int);
- method public abstract org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public abstract java.net.InetAddress getLocalAddress();
- method public abstract org.apache.http.HttpHost getProxyHost();
- method public abstract org.apache.http.HttpHost getTargetHost();
- method public abstract org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public abstract boolean isLayered();
- method public abstract boolean isSecure();
- method public abstract boolean isTunnelled();
- }
-
- public static final class RouteInfo.LayerType extends java.lang.Enum {
- method public static org.apache.http.conn.routing.RouteInfo.LayerType valueOf(java.lang.String);
- method public static final org.apache.http.conn.routing.RouteInfo.LayerType[] values();
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType LAYERED;
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType PLAIN;
- }
-
- public static final class RouteInfo.TunnelType extends java.lang.Enum {
- method public static org.apache.http.conn.routing.RouteInfo.TunnelType valueOf(java.lang.String);
- method public static final org.apache.http.conn.routing.RouteInfo.TunnelType[] values();
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType PLAIN;
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType TUNNELLED;
- }
-
- public final deprecated class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
- ctor public RouteTracker(org.apache.http.HttpHost, java.net.InetAddress);
- ctor public RouteTracker(org.apache.http.conn.routing.HttpRoute);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public final void connectProxy(org.apache.http.HttpHost, boolean);
- method public final void connectTarget(boolean);
- method public final boolean equals(java.lang.Object);
- method public final int getHopCount();
- method public final org.apache.http.HttpHost getHopTarget(int);
- method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public final java.net.InetAddress getLocalAddress();
- method public final org.apache.http.HttpHost getProxyHost();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public final int hashCode();
- method public final boolean isConnected();
- method public final boolean isLayered();
- method public final boolean isSecure();
- method public final boolean isTunnelled();
- method public final void layerProtocol(boolean);
- method public final org.apache.http.conn.routing.HttpRoute toRoute();
- method public final java.lang.String toString();
- method public final void tunnelProxy(org.apache.http.HttpHost, boolean);
- method public final void tunnelTarget(boolean);
- }
-
}
package org.apache.http.conn.scheme {
@@ -55976,37 +54895,6 @@
method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException;
}
- public final deprecated class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
- ctor public PlainSocketFactory(org.apache.http.conn.scheme.HostNameResolver);
- ctor public PlainSocketFactory();
- method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.Socket createSocket();
- method public static org.apache.http.conn.scheme.PlainSocketFactory getSocketFactory();
- method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
- }
-
- public final deprecated class Scheme {
- ctor public Scheme(java.lang.String, org.apache.http.conn.scheme.SocketFactory, int);
- method public final boolean equals(java.lang.Object);
- method public final int getDefaultPort();
- method public final java.lang.String getName();
- method public final org.apache.http.conn.scheme.SocketFactory getSocketFactory();
- method public final boolean isLayered();
- method public final int resolvePort(int);
- method public final java.lang.String toString();
- }
-
- public final deprecated class SchemeRegistry {
- ctor public SchemeRegistry();
- method public final synchronized org.apache.http.conn.scheme.Scheme get(java.lang.String);
- method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(java.lang.String);
- method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(org.apache.http.HttpHost);
- method public final synchronized java.util.List<java.lang.String> getSchemeNames();
- method public final synchronized org.apache.http.conn.scheme.Scheme register(org.apache.http.conn.scheme.Scheme);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.conn.scheme.Scheme>);
- method public final synchronized org.apache.http.conn.scheme.Scheme unregister(java.lang.String);
- }
-
public abstract deprecated interface SocketFactory {
method public abstract java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws org.apache.http.conn.ConnectTimeoutException, java.io.IOException, java.net.UnknownHostException;
method public abstract java.net.Socket createSocket() throws java.io.IOException;
@@ -56076,1818 +54964,8 @@
}
-package org.apache.http.conn.util {
-
- public deprecated class InetAddressUtils {
- method public static boolean isIPv4Address(java.lang.String);
- method public static boolean isIPv6Address(java.lang.String);
- method public static boolean isIPv6HexCompressedAddress(java.lang.String);
- method public static boolean isIPv6StdAddress(java.lang.String);
- }
-
-}
-
-package org.apache.http.cookie {
-
- public abstract deprecated interface ClientCookie implements org.apache.http.cookie.Cookie {
- method public abstract boolean containsAttribute(java.lang.String);
- method public abstract java.lang.String getAttribute(java.lang.String);
- field public static final java.lang.String COMMENTURL_ATTR = "commenturl";
- field public static final java.lang.String COMMENT_ATTR = "comment";
- field public static final java.lang.String DISCARD_ATTR = "discard";
- field public static final java.lang.String DOMAIN_ATTR = "domain";
- field public static final java.lang.String EXPIRES_ATTR = "expires";
- field public static final java.lang.String MAX_AGE_ATTR = "max-age";
- field public static final java.lang.String PATH_ATTR = "path";
- field public static final java.lang.String PORT_ATTR = "port";
- field public static final java.lang.String SECURE_ATTR = "secure";
- field public static final java.lang.String VERSION_ATTR = "version";
- }
-
- public abstract deprecated interface Cookie {
- method public abstract java.lang.String getComment();
- method public abstract java.lang.String getCommentURL();
- method public abstract java.lang.String getDomain();
- method public abstract java.util.Date getExpiryDate();
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getPath();
- method public abstract int[] getPorts();
- method public abstract java.lang.String getValue();
- method public abstract int getVersion();
- method public abstract boolean isExpired(java.util.Date);
- method public abstract boolean isPersistent();
- method public abstract boolean isSecure();
- }
-
- public abstract deprecated interface CookieAttributeHandler {
- method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public abstract void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class CookieIdentityComparator implements java.util.Comparator java.io.Serializable {
- ctor public CookieIdentityComparator();
- method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
- }
-
- public final deprecated class CookieOrigin {
- ctor public CookieOrigin(java.lang.String, int, java.lang.String, boolean);
- method public java.lang.String getHost();
- method public java.lang.String getPath();
- method public int getPort();
- method public boolean isSecure();
- }
-
- public deprecated class CookiePathComparator implements java.util.Comparator java.io.Serializable {
- ctor public CookiePathComparator();
- method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
- }
-
- public abstract deprecated interface CookieSpec {
- method public abstract java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public abstract int getVersion();
- method public abstract org.apache.http.Header getVersionHeader();
- method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public abstract java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public abstract deprecated interface CookieSpecFactory {
- method public abstract org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public final deprecated class CookieSpecRegistry {
- ctor public CookieSpecRegistry();
- method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
- method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String) throws java.lang.IllegalStateException;
- method public synchronized java.util.List<java.lang.String> getSpecNames();
- method public synchronized void register(java.lang.String, org.apache.http.cookie.CookieSpecFactory);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.cookie.CookieSpecFactory>);
- method public synchronized void unregister(java.lang.String);
- }
-
- public deprecated class MalformedCookieException extends org.apache.http.ProtocolException {
- ctor public MalformedCookieException();
- ctor public MalformedCookieException(java.lang.String);
- ctor public MalformedCookieException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface SM {
- field public static final java.lang.String COOKIE = "Cookie";
- field public static final java.lang.String COOKIE2 = "Cookie2";
- field public static final java.lang.String SET_COOKIE = "Set-Cookie";
- field public static final java.lang.String SET_COOKIE2 = "Set-Cookie2";
- }
-
- public abstract deprecated interface SetCookie implements org.apache.http.cookie.Cookie {
- method public abstract void setComment(java.lang.String);
- method public abstract void setDomain(java.lang.String);
- method public abstract void setExpiryDate(java.util.Date);
- method public abstract void setPath(java.lang.String);
- method public abstract void setSecure(boolean);
- method public abstract void setValue(java.lang.String);
- method public abstract void setVersion(int);
- }
-
- public abstract deprecated interface SetCookie2 implements org.apache.http.cookie.SetCookie {
- method public abstract void setCommentURL(java.lang.String);
- method public abstract void setDiscard(boolean);
- method public abstract void setPorts(int[]);
- }
-
-}
-
-package org.apache.http.cookie.params {
-
- public abstract deprecated interface CookieSpecPNames {
- field public static final java.lang.String DATE_PATTERNS = "http.protocol.cookie-datepatterns";
- field public static final java.lang.String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
- }
-
- public deprecated class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public CookieSpecParamBean(org.apache.http.params.HttpParams);
- method public void setDatePatterns(java.util.Collection<java.lang.String>);
- method public void setSingleHeader(boolean);
- }
-
-}
-
-package org.apache.http.entity {
-
- public abstract deprecated class AbstractHttpEntity implements org.apache.http.HttpEntity {
- ctor protected AbstractHttpEntity();
- method public void consumeContent() throws java.io.IOException, java.lang.UnsupportedOperationException;
- method public org.apache.http.Header getContentEncoding();
- method public org.apache.http.Header getContentType();
- method public boolean isChunked();
- method public void setChunked(boolean);
- method public void setContentEncoding(org.apache.http.Header);
- method public void setContentEncoding(java.lang.String);
- method public void setContentType(org.apache.http.Header);
- method public void setContentType(java.lang.String);
- field protected boolean chunked;
- field protected org.apache.http.Header contentEncoding;
- field protected org.apache.http.Header contentType;
- }
-
- public deprecated class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public BasicHttpEntity();
- method public java.io.InputStream getContent() throws java.lang.IllegalStateException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void setContent(java.io.InputStream);
- method public void setContentLength(long);
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper {
- ctor public BufferedHttpEntity(org.apache.http.HttpEntity) throws java.io.IOException;
- }
-
- public deprecated class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public ByteArrayEntity(byte[]);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent();
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final byte[] content;
- }
-
- public abstract deprecated interface ContentLengthStrategy {
- method public abstract long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- field public static final int CHUNKED = -2; // 0xfffffffe
- field public static final int IDENTITY = -1; // 0xffffffff
- }
-
- public abstract deprecated interface ContentProducer {
- method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity {
- ctor public EntityTemplate(org.apache.http.entity.ContentProducer);
- method public java.io.InputStream getContent();
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public FileEntity(java.io.File, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final java.io.File file;
- }
-
- public deprecated class HttpEntityWrapper implements org.apache.http.HttpEntity {
- ctor public HttpEntityWrapper(org.apache.http.HttpEntity);
- method public void consumeContent() throws java.io.IOException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public org.apache.http.Header getContentEncoding();
- method public long getContentLength();
- method public org.apache.http.Header getContentType();
- method public boolean isChunked();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected org.apache.http.HttpEntity wrappedEntity;
- }
-
- public deprecated class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public InputStreamEntity(java.io.InputStream, long);
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public SerializableEntity(java.io.Serializable, boolean) throws java.io.IOException;
- method public java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public StringEntity(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
- ctor public StringEntity(java.lang.String) throws java.io.UnsupportedEncodingException;
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final byte[] content;
- }
-
-}
-
-package org.apache.http.impl {
-
- public abstract deprecated class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection {
- ctor public AbstractHttpClientConnection();
- method protected abstract void assertOpen() throws java.lang.IllegalStateException;
- method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
- method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
- method protected org.apache.http.HttpResponseFactory createHttpResponseFactory();
- method protected org.apache.http.io.HttpMessageWriter createRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method protected org.apache.http.io.HttpMessageParser createResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected void doFlush() throws java.io.IOException;
- method public void flush() throws java.io.IOException;
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method public boolean isResponseAvailable(int) throws java.io.IOException;
- method public boolean isStale();
- method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection {
- ctor public AbstractHttpServerConnection();
- method protected abstract void assertOpen() throws java.lang.IllegalStateException;
- method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
- method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
- method protected org.apache.http.HttpRequestFactory createHttpRequestFactory();
- method protected org.apache.http.io.HttpMessageParser createRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.io.HttpMessageWriter createResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method protected void doFlush() throws java.io.IOException;
- method public void flush() throws java.io.IOException;
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method public boolean isStale();
- method public void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
- ctor public DefaultConnectionReuseStrategy();
- method protected org.apache.http.TokenIterator createTokenIterator(org.apache.http.HeaderIterator);
- method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection {
- ctor public DefaultHttpClientConnection();
- method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory {
- ctor public DefaultHttpRequestFactory();
- method public org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
- method public org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
- }
-
- public deprecated class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory {
- ctor public DefaultHttpResponseFactory(org.apache.http.ReasonPhraseCatalog);
- ctor public DefaultHttpResponseFactory();
- method protected java.util.Locale determineLocale(org.apache.http.protocol.HttpContext);
- method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
- method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
- field protected final org.apache.http.ReasonPhraseCatalog reasonCatalog;
- }
-
- public deprecated class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection {
- ctor public DefaultHttpServerConnection();
- method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog {
- ctor protected EnglishReasonPhraseCatalog();
- method public java.lang.String getReason(int, java.util.Locale);
- field public static final org.apache.http.impl.EnglishReasonPhraseCatalog INSTANCE;
- }
-
- public deprecated class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics {
- ctor public HttpConnectionMetricsImpl(org.apache.http.io.HttpTransportMetrics, org.apache.http.io.HttpTransportMetrics);
- method public java.lang.Object getMetric(java.lang.String);
- method public long getReceivedBytesCount();
- method public long getRequestCount();
- method public long getResponseCount();
- method public long getSentBytesCount();
- method public void incrementRequestCount();
- method public void incrementResponseCount();
- method public void reset();
- method public void setMetric(java.lang.String, java.lang.Object);
- field public static final java.lang.String RECEIVED_BYTES_COUNT = "http.received-bytes-count";
- field public static final java.lang.String REQUEST_COUNT = "http.request-count";
- field public static final java.lang.String RESPONSE_COUNT = "http.response-count";
- field public static final java.lang.String SENT_BYTES_COUNT = "http.sent-bytes-count";
- }
-
- public deprecated class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
- ctor public NoConnectionReuseStrategy();
- method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection {
- ctor public SocketHttpClientConnection();
- method protected void assertNotOpen();
- method protected void assertOpen();
- method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void close() throws java.io.IOException;
- method protected org.apache.http.io.SessionInputBuffer createSessionInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected org.apache.http.io.SessionOutputBuffer createSessionOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method protected java.net.Socket getSocket();
- method public int getSocketTimeout();
- method public boolean isOpen();
- method public void setSocketTimeout(int);
- method public void shutdown() throws java.io.IOException;
- }
-
- public deprecated class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection {
- ctor public SocketHttpServerConnection();
- method protected void assertNotOpen();
- method protected void assertOpen();
- method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void close() throws java.io.IOException;
- method protected org.apache.http.io.SessionInputBuffer createHttpDataReceiver(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected org.apache.http.io.SessionOutputBuffer createHttpDataTransmitter(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method protected java.net.Socket getSocket();
- method public int getSocketTimeout();
- method public boolean isOpen();
- method public void setSocketTimeout(int);
- method public void shutdown() throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.impl.auth {
-
- public abstract deprecated class AuthSchemeBase implements org.apache.http.auth.AuthScheme {
- ctor public AuthSchemeBase();
- method public boolean isProxy();
- method protected abstract void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- method public void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public deprecated class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme {
- ctor public BasicScheme();
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public static org.apache.http.Header authenticate(org.apache.http.auth.Credentials, java.lang.String, boolean);
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- }
-
- public deprecated class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
- ctor public BasicSchemeFactory();
- method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme {
- ctor public DigestScheme();
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public static java.lang.String createCnonce();
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- method public void overrideParamter(java.lang.String, java.lang.String);
- }
-
- public deprecated class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
- ctor public DigestSchemeFactory();
- method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated interface NTLMEngine {
- method public abstract java.lang.String generateType1Msg(java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
- method public abstract java.lang.String generateType3Msg(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
- }
-
- public deprecated class NTLMEngineException extends org.apache.http.auth.AuthenticationException {
- ctor public NTLMEngineException();
- ctor public NTLMEngineException(java.lang.String);
- ctor public NTLMEngineException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase {
- ctor public NTLMScheme(org.apache.http.impl.auth.NTLMEngine);
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public java.lang.String getParameter(java.lang.String);
- method public java.lang.String getRealm();
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public abstract deprecated class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase {
- ctor public RFC2617Scheme();
- method public java.lang.String getParameter(java.lang.String);
- method protected java.util.Map<java.lang.String, java.lang.String> getParameters();
- method public java.lang.String getRealm();
- method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public deprecated class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException {
- ctor public UnsupportedDigestAlgorithmException();
- ctor public UnsupportedDigestAlgorithmException(java.lang.String);
- ctor public UnsupportedDigestAlgorithmException(java.lang.String, java.lang.Throwable);
- }
-
-}
-
-package org.apache.http.impl.client {
-
- public abstract deprecated class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler {
- ctor public AbstractAuthenticationHandler();
- method protected java.util.List<java.lang.String> getAuthPreferences();
- method protected java.util.Map<java.lang.String, org.apache.http.Header> parseChallenges(org.apache.http.Header[]) throws org.apache.http.auth.MalformedChallengeException;
- method public org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
- }
-
- public abstract deprecated class AbstractHttpClient implements org.apache.http.client.HttpClient {
- ctor protected AbstractHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
- method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public synchronized void clearRequestInterceptors();
- method public synchronized void clearResponseInterceptors();
- method protected abstract org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
- method protected abstract org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
- method protected org.apache.http.client.RequestDirector createClientRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
- method protected abstract org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
- method protected abstract org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
- method protected abstract org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
- method protected abstract org.apache.http.client.CookieStore createCookieStore();
- method protected abstract org.apache.http.client.CredentialsProvider createCredentialsProvider();
- method protected abstract org.apache.http.protocol.HttpContext createHttpContext();
- method protected abstract org.apache.http.params.HttpParams createHttpParams();
- method protected abstract org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
- method protected abstract org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
- method protected abstract org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
- method protected abstract org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
- method protected abstract org.apache.http.client.RedirectHandler createRedirectHandler();
- method protected abstract org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
- method protected abstract org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
- method protected abstract org.apache.http.client.UserTokenHandler createUserTokenHandler();
- method protected org.apache.http.params.HttpParams determineParams(org.apache.http.HttpRequest);
- method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final synchronized org.apache.http.auth.AuthSchemeRegistry getAuthSchemes();
- method public final synchronized org.apache.http.conn.ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy();
- method public final synchronized org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public final synchronized org.apache.http.ConnectionReuseStrategy getConnectionReuseStrategy();
- method public final synchronized org.apache.http.cookie.CookieSpecRegistry getCookieSpecs();
- method public final synchronized org.apache.http.client.CookieStore getCookieStore();
- method public final synchronized org.apache.http.client.CredentialsProvider getCredentialsProvider();
- method protected final synchronized org.apache.http.protocol.BasicHttpProcessor getHttpProcessor();
- method public final synchronized org.apache.http.client.HttpRequestRetryHandler getHttpRequestRetryHandler();
- method public final synchronized org.apache.http.params.HttpParams getParams();
- method public final synchronized org.apache.http.client.AuthenticationHandler getProxyAuthenticationHandler();
- method public final synchronized org.apache.http.client.RedirectHandler getRedirectHandler();
- method public final synchronized org.apache.http.protocol.HttpRequestExecutor getRequestExecutor();
- method public synchronized org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public synchronized int getRequestInterceptorCount();
- method public synchronized org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public synchronized int getResponseInterceptorCount();
- method public final synchronized org.apache.http.conn.routing.HttpRoutePlanner getRoutePlanner();
- method public final synchronized org.apache.http.client.AuthenticationHandler getTargetAuthenticationHandler();
- method public final synchronized org.apache.http.client.UserTokenHandler getUserTokenHandler();
- method public void removeRequestInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpRequestInterceptor>);
- method public void removeResponseInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpResponseInterceptor>);
- method public synchronized void setAuthSchemes(org.apache.http.auth.AuthSchemeRegistry);
- method public synchronized void setCookieSpecs(org.apache.http.cookie.CookieSpecRegistry);
- method public synchronized void setCookieStore(org.apache.http.client.CookieStore);
- method public synchronized void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
- method public synchronized void setHttpRequestRetryHandler(org.apache.http.client.HttpRequestRetryHandler);
- method public synchronized void setKeepAliveStrategy(org.apache.http.conn.ConnectionKeepAliveStrategy);
- method public synchronized void setParams(org.apache.http.params.HttpParams);
- method public synchronized void setProxyAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
- method public synchronized void setRedirectHandler(org.apache.http.client.RedirectHandler);
- method public synchronized void setReuseStrategy(org.apache.http.ConnectionReuseStrategy);
- method public synchronized void setRoutePlanner(org.apache.http.conn.routing.HttpRoutePlanner);
- method public synchronized void setTargetAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
- method public synchronized void setUserTokenHandler(org.apache.http.client.UserTokenHandler);
- }
-
- public deprecated class BasicCookieStore implements org.apache.http.client.CookieStore {
- ctor public BasicCookieStore();
- method public synchronized void addCookie(org.apache.http.cookie.Cookie);
- method public synchronized void addCookies(org.apache.http.cookie.Cookie[]);
- method public synchronized void clear();
- method public synchronized boolean clearExpired(java.util.Date);
- method public synchronized java.util.List<org.apache.http.cookie.Cookie> getCookies();
- }
-
- public deprecated class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider {
- ctor public BasicCredentialsProvider();
- method public synchronized void clear();
- method public synchronized org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
- method public synchronized void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
- }
-
- public deprecated class BasicResponseHandler implements org.apache.http.client.ResponseHandler {
- ctor public BasicResponseHandler();
- method public java.lang.String handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.HttpResponseException, java.io.IOException;
- }
-
- public deprecated class ClientParamsStack extends org.apache.http.params.AbstractHttpParams {
- ctor public ClientParamsStack(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack);
- ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- method public org.apache.http.params.HttpParams copy();
- method public final org.apache.http.params.HttpParams getApplicationParams();
- method public final org.apache.http.params.HttpParams getClientParams();
- method public final org.apache.http.params.HttpParams getOverrideParams();
- method public java.lang.Object getParameter(java.lang.String);
- method public final org.apache.http.params.HttpParams getRequestParams();
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object) throws java.lang.UnsupportedOperationException;
- field protected final org.apache.http.params.HttpParams applicationParams;
- field protected final org.apache.http.params.HttpParams clientParams;
- field protected final org.apache.http.params.HttpParams overrideParams;
- field protected final org.apache.http.params.HttpParams requestParams;
- }
-
- public deprecated class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy {
- ctor public DefaultConnectionKeepAliveStrategy();
- method public long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient {
- ctor public DefaultHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
- ctor public DefaultHttpClient(org.apache.http.params.HttpParams);
- ctor public DefaultHttpClient();
- method protected org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
- method protected org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
- method protected org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
- method protected org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
- method protected org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
- method protected org.apache.http.client.CookieStore createCookieStore();
- method protected org.apache.http.client.CredentialsProvider createCredentialsProvider();
- method protected org.apache.http.protocol.HttpContext createHttpContext();
- method protected org.apache.http.params.HttpParams createHttpParams();
- method protected org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
- method protected org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
- method protected org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
- method protected org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
- method protected org.apache.http.client.RedirectHandler createRedirectHandler();
- method protected org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
- method protected org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
- method protected org.apache.http.client.UserTokenHandler createUserTokenHandler();
- }
-
- public deprecated class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler {
- ctor public DefaultHttpRequestRetryHandler(int, boolean);
- ctor public DefaultHttpRequestRetryHandler();
- method public int getRetryCount();
- method public boolean isRequestSentRetryEnabled();
- method public boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
- ctor public DefaultProxyAuthenticationHandler();
- method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler {
- ctor public DefaultRedirectHandler();
- method public java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
- method public boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultRequestDirector implements org.apache.http.client.RequestDirector {
- ctor public DefaultRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpRequest createConnectRequest(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext);
- method protected boolean createTunnelToProxy(org.apache.http.conn.routing.HttpRoute, int, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected boolean createTunnelToTarget(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method protected void establishRoute(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.impl.client.RoutedRequest handleResponse(org.apache.http.impl.client.RoutedRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected void releaseConnection();
- method protected void rewriteRequestURI(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute) throws org.apache.http.ProtocolException;
- field protected final org.apache.http.conn.ClientConnectionManager connManager;
- field protected final org.apache.http.protocol.HttpProcessor httpProcessor;
- field protected final org.apache.http.conn.ConnectionKeepAliveStrategy keepAliveStrategy;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- field protected final org.apache.http.params.HttpParams params;
- field protected final org.apache.http.client.RedirectHandler redirectHandler;
- field protected final org.apache.http.protocol.HttpRequestExecutor requestExec;
- field protected final org.apache.http.client.HttpRequestRetryHandler retryHandler;
- field protected final org.apache.http.ConnectionReuseStrategy reuseStrategy;
- field protected final org.apache.http.conn.routing.HttpRoutePlanner routePlanner;
- }
-
- public deprecated class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
- ctor public DefaultTargetAuthenticationHandler();
- method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler {
- ctor public DefaultUserTokenHandler();
- method public java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public EntityEnclosingRequestWrapper(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.ProtocolException;
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class RedirectLocations {
- ctor public RedirectLocations();
- method public void add(java.net.URI);
- method public boolean contains(java.net.URI);
- method public boolean remove(java.net.URI);
- }
-
- public deprecated class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest {
- ctor public RequestWrapper(org.apache.http.HttpRequest) throws org.apache.http.ProtocolException;
- method public void abort() throws java.lang.UnsupportedOperationException;
- method public int getExecCount();
- method public java.lang.String getMethod();
- method public org.apache.http.HttpRequest getOriginal();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- method public java.net.URI getURI();
- method public void incrementExecCount();
- method public boolean isAborted();
- method public boolean isRepeatable();
- method public void resetHeaders();
- method public void setMethod(java.lang.String);
- method public void setProtocolVersion(org.apache.http.ProtocolVersion);
- method public void setURI(java.net.URI);
- }
-
- public deprecated class RoutedRequest {
- ctor public RoutedRequest(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute);
- method public final org.apache.http.impl.client.RequestWrapper getRequest();
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- field protected final org.apache.http.impl.client.RequestWrapper request;
- field protected final org.apache.http.conn.routing.HttpRoute route;
- }
-
- public deprecated class TunnelRefusedException extends org.apache.http.HttpException {
- ctor public TunnelRefusedException(java.lang.String, org.apache.http.HttpResponse);
- method public org.apache.http.HttpResponse getResponse();
- }
-
-}
-
-package org.apache.http.impl.conn {
-
- public abstract deprecated class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection {
- ctor protected AbstractClientConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.conn.OperatedClientConnection);
- method public void abortConnection();
- method protected final void assertNotAborted() throws java.io.InterruptedIOException;
- method protected final void assertValid(org.apache.http.conn.OperatedClientConnection);
- method protected void detach();
- method public void flush() throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method protected org.apache.http.conn.ClientConnectionManager getManager();
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method public javax.net.ssl.SSLSession getSSLSession();
- method public int getSocketTimeout();
- method protected org.apache.http.conn.OperatedClientConnection getWrappedConnection();
- method public boolean isMarkedReusable();
- method public boolean isOpen();
- method public boolean isResponseAvailable(int) throws java.io.IOException;
- method public boolean isSecure();
- method public boolean isStale();
- method public void markReusable();
- method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void releaseConnection();
- method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void setIdleDuration(long, java.util.concurrent.TimeUnit);
- method public void setSocketTimeout(int);
- method public void unmarkReusable();
- }
-
- public abstract deprecated class AbstractPoolEntry {
- ctor protected AbstractPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute);
- method public java.lang.Object getState();
- method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void setState(java.lang.Object);
- method protected void shutdownEntry();
- method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected final org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected final org.apache.http.conn.OperatedClientConnection connection;
- field protected volatile org.apache.http.conn.routing.HttpRoute route;
- field protected volatile java.lang.Object state;
- field protected volatile org.apache.http.conn.routing.RouteTracker tracker;
- }
-
- public abstract deprecated class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter {
- ctor protected AbstractPooledConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.impl.conn.AbstractPoolEntry);
- method protected final void assertAttached();
- method public void close() throws java.io.IOException;
- method public org.apache.http.conn.routing.HttpRoute getRoute();
- method public java.lang.Object getState();
- method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void setState(java.lang.Object);
- method public void shutdown() throws java.io.IOException;
- method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected volatile org.apache.http.impl.conn.AbstractPoolEntry poolEntry;
- }
-
- public deprecated class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection {
- ctor public DefaultClientConnection();
- method public final java.net.Socket getSocket();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final boolean isSecure();
- method public void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
- method public void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator {
- ctor public DefaultClientConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.OperatedClientConnection createConnection();
- method public void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected void prepareSocket(java.net.Socket, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
- ctor public DefaultHttpRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public DefaultResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class IdleConnectionHandler {
- ctor public IdleConnectionHandler();
- method public void add(org.apache.http.HttpConnection, long, java.util.concurrent.TimeUnit);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long);
- method public boolean remove(org.apache.http.HttpConnection);
- method public void removeAll();
- }
-
- public deprecated class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
- ctor public LoggingSessionInputBuffer(org.apache.http.io.SessionInputBuffer, org.apache.http.impl.conn.Wire);
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method public boolean isDataAvailable(int) throws java.io.IOException;
- method public int read(byte[], int, int) throws java.io.IOException;
- method public int read() throws java.io.IOException;
- method public int read(byte[]) throws java.io.IOException;
- method public java.lang.String readLine() throws java.io.IOException;
- method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
- public deprecated class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
- ctor public LoggingSessionOutputBuffer(org.apache.http.io.SessionOutputBuffer, org.apache.http.impl.conn.Wire);
- method public void flush() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method public void write(byte[], int, int) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method public void write(byte[]) throws java.io.IOException;
- method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public void writeLine(java.lang.String) throws java.io.IOException;
- }
-
- public deprecated class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
- ctor public ProxySelectorRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry, java.net.ProxySelector);
- method protected java.net.Proxy chooseProxy(java.util.List<java.net.Proxy>, org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext);
- method protected org.apache.http.HttpHost determineProxy(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method protected java.lang.String getHost(java.net.InetSocketAddress);
- method public java.net.ProxySelector getProxySelector();
- method public void setProxySelector(java.net.ProxySelector);
- field protected java.net.ProxySelector proxySelector;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager {
- ctor public SingleClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- method protected final void assertStillUp() throws java.lang.IllegalStateException;
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.ManagedClientConnection getConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public final org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method protected void revokeConnection();
- method public void shutdown();
- field public static final java.lang.String MISUSE_MESSAGE = "Invalid use of SingleClientConnManager: connection still allocated.\nMake sure to release the connection before allocating another one.";
- field protected boolean alwaysShutDown;
- field protected org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected long connectionExpiresTime;
- field protected volatile boolean isShutDown;
- field protected long lastReleaseTime;
- field protected org.apache.http.impl.conn.SingleClientConnManager.ConnAdapter managedConn;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- field protected org.apache.http.impl.conn.SingleClientConnManager.PoolEntry uniquePoolEntry;
- }
-
- protected class SingleClientConnManager.ConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
- ctor protected SingleClientConnManager.ConnAdapter(org.apache.http.impl.conn.SingleClientConnManager.PoolEntry, org.apache.http.conn.routing.HttpRoute);
- }
-
- protected class SingleClientConnManager.PoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
- ctor protected SingleClientConnManager.PoolEntry();
- method protected void close() throws java.io.IOException;
- method protected void shutdown() throws java.io.IOException;
- }
-
- public deprecated class Wire {
- ctor public Wire(org.apache.commons.logging.Log);
- method public boolean enabled();
- method public void input(java.io.InputStream) throws java.io.IOException;
- method public void input(byte[], int, int) throws java.io.IOException;
- method public void input(byte[]) throws java.io.IOException;
- method public void input(int) throws java.io.IOException;
- method public void input(java.lang.String) throws java.io.IOException;
- method public void output(java.io.InputStream) throws java.io.IOException;
- method public void output(byte[], int, int) throws java.io.IOException;
- method public void output(byte[]) throws java.io.IOException;
- method public void output(int) throws java.io.IOException;
- method public void output(java.lang.String) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.impl.conn.tsccm {
-
- public abstract deprecated class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler {
- ctor protected AbstractConnPool();
- method protected void closeConnection(org.apache.http.conn.OperatedClientConnection);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method public abstract void deleteClosedConnections();
- method public void enableConnectionGC() throws java.lang.IllegalStateException;
- method public abstract void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
- method public final org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- method protected abstract void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
- method public void handleReference(java.lang.ref.Reference);
- method public abstract org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public void shutdown();
- field protected org.apache.http.impl.conn.IdleConnectionHandler idleConnHandler;
- field protected volatile boolean isShutDown;
- field protected java.util.Set<org.apache.http.impl.conn.tsccm.BasicPoolEntryRef> issuedConnections;
- field protected int numConnections;
- field protected final java.util.concurrent.locks.Lock poolLock;
- field protected java.lang.ref.ReferenceQueue<java.lang.Object> refQueue;
- }
-
- public deprecated class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
- ctor public BasicPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute, java.lang.ref.ReferenceQueue<java.lang.Object>);
- method protected final org.apache.http.conn.OperatedClientConnection getConnection();
- method protected final org.apache.http.conn.routing.HttpRoute getPlannedRoute();
- method protected final org.apache.http.impl.conn.tsccm.BasicPoolEntryRef getWeakRef();
- }
-
- public deprecated class BasicPoolEntryRef extends java.lang.ref.WeakReference {
- ctor public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry, java.lang.ref.ReferenceQueue<java.lang.Object>);
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- }
-
- public deprecated class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
- ctor protected BasicPooledConnAdapter(org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager, org.apache.http.impl.conn.AbstractPoolEntry);
- method protected org.apache.http.impl.conn.AbstractPoolEntry getPoolEntry();
- }
-
- public deprecated class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool {
- ctor public ConnPoolByRoute(org.apache.http.conn.ClientConnectionOperator, org.apache.http.params.HttpParams);
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry createEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, org.apache.http.conn.ClientConnectionOperator);
- method protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> createFreeConnQueue();
- method protected java.util.Map<org.apache.http.conn.routing.HttpRoute, org.apache.http.impl.conn.tsccm.RouteSpecificPool> createRouteToPoolMap();
- method protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> createWaitingThreadQueue();
- method public void deleteClosedConnections();
- method protected void deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method protected void deleteLeastUsedEntry();
- method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
- method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntryBlocking(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit, org.apache.http.impl.conn.tsccm.WaitingThreadAborter) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getFreeEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, java.lang.Object);
- method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool getRoutePool(org.apache.http.conn.routing.HttpRoute, boolean);
- method protected void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool newRouteSpecificPool(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.WaitingThread newWaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method protected void notifyWaitingThread(org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method public org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- field protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> freeConnections;
- field protected final int maxTotalConnections;
- field protected final org.apache.http.conn.ClientConnectionOperator operator;
- field protected final java.util.Map<org.apache.http.conn.routing.HttpRoute, org.apache.http.impl.conn.tsccm.RouteSpecificPool> routeToPool;
- field protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads;
- }
-
- public abstract deprecated interface PoolEntryRequest {
- method public abstract void abortRequest();
- method public abstract org.apache.http.impl.conn.tsccm.BasicPoolEntry getPoolEntry(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- }
-
- public abstract deprecated interface RefQueueHandler {
- method public abstract void handleReference(java.lang.ref.Reference<?>);
- }
-
- public deprecated class RefQueueWorker implements java.lang.Runnable {
- ctor public RefQueueWorker(java.lang.ref.ReferenceQueue<?>, org.apache.http.impl.conn.tsccm.RefQueueHandler);
- method public void run();
- method public void shutdown();
- field protected final org.apache.http.impl.conn.tsccm.RefQueueHandler refHandler;
- field protected final java.lang.ref.ReferenceQueue<?> refQueue;
- field protected volatile java.lang.Thread workerThread;
- }
-
- public deprecated class RouteSpecificPool {
- ctor public RouteSpecificPool(org.apache.http.conn.routing.HttpRoute, int);
- method public org.apache.http.impl.conn.tsccm.BasicPoolEntry allocEntry(java.lang.Object);
- method public void createdEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public boolean deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public void dropEntry();
- method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public int getCapacity();
- method public final int getEntryCount();
- method public final int getMaxEntries();
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- method public boolean hasThread();
- method public boolean isUnused();
- method public org.apache.http.impl.conn.tsccm.WaitingThread nextThread();
- method public void queueThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- method public void removeThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- field protected final java.util.LinkedList<org.apache.http.impl.conn.tsccm.BasicPoolEntry> freeEntries;
- field protected final int maxEntries;
- field protected int numEntries;
- field protected final org.apache.http.conn.routing.HttpRoute route;
- field protected final java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads;
- }
-
- public deprecated class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager {
- ctor public ThreadSafeClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method protected org.apache.http.impl.conn.tsccm.AbstractConnPool createConnectionPool(org.apache.http.params.HttpParams);
- method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
- method public int getConnectionsInPool();
- method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public void shutdown();
- field protected org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected final org.apache.http.impl.conn.tsccm.AbstractConnPool connectionPool;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class WaitingThread {
- ctor public WaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method public boolean await(java.util.Date) throws java.lang.InterruptedException;
- method public final java.util.concurrent.locks.Condition getCondition();
- method public final org.apache.http.impl.conn.tsccm.RouteSpecificPool getPool();
- method public final java.lang.Thread getThread();
- method public void interrupt();
- method public void wakeup();
- }
-
- public deprecated class WaitingThreadAborter {
- ctor public WaitingThreadAborter();
- method public void abort();
- method public void setWaitingThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- }
-
-}
-
-package org.apache.http.impl.cookie {
-
- public abstract deprecated class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public AbstractCookieAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public abstract deprecated class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec {
- ctor public AbstractCookieSpec();
- method protected org.apache.http.cookie.CookieAttributeHandler findAttribHandler(java.lang.String);
- method protected org.apache.http.cookie.CookieAttributeHandler getAttribHandler(java.lang.String);
- method protected java.util.Collection<org.apache.http.cookie.CookieAttributeHandler> getAttribHandlers();
- method public void registerAttribHandler(java.lang.String, org.apache.http.cookie.CookieAttributeHandler);
- }
-
- public deprecated class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie {
- ctor public BasicClientCookie(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public boolean containsAttribute(java.lang.String);
- method public java.lang.String getAttribute(java.lang.String);
- method public java.lang.String getComment();
- method public java.lang.String getCommentURL();
- method public java.lang.String getDomain();
- method public java.util.Date getExpiryDate();
- method public java.lang.String getName();
- method public java.lang.String getPath();
- method public int[] getPorts();
- method public java.lang.String getValue();
- method public int getVersion();
- method public boolean isExpired(java.util.Date);
- method public boolean isPersistent();
- method public boolean isSecure();
- method public void setAttribute(java.lang.String, java.lang.String);
- method public void setComment(java.lang.String);
- method public void setDomain(java.lang.String);
- method public void setExpiryDate(java.util.Date);
- method public void setPath(java.lang.String);
- method public void setSecure(boolean);
- method public void setValue(java.lang.String);
- method public void setVersion(int);
- }
-
- public deprecated class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 {
- ctor public BasicClientCookie2(java.lang.String, java.lang.String);
- method public void setCommentURL(java.lang.String);
- method public void setDiscard(boolean);
- method public void setPorts(int[]);
- }
-
- public deprecated class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicCommentHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public BasicDomainHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicExpiresHandler(java.lang.String[]);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicMaxAgeHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public BasicPathHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicSecureHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BestMatchSpec implements org.apache.http.cookie.CookieSpec {
- ctor public BestMatchSpec(java.lang.String[], boolean);
- ctor public BestMatchSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public BestMatchSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public BrowserCompatSpec(java.lang.String[]);
- ctor public BrowserCompatSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- field protected static final java.lang.String[] DATE_PATTERNS;
- }
-
- public deprecated class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public BrowserCompatSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec {
- ctor public CookieSpecBase();
- method protected static java.lang.String getDefaultDomain(org.apache.http.cookie.CookieOrigin);
- method protected static java.lang.String getDefaultPath(org.apache.http.cookie.CookieOrigin);
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method protected java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.HeaderElement[], org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class DateParseException extends java.lang.Exception {
- ctor public DateParseException();
- ctor public DateParseException(java.lang.String);
- }
-
- public final deprecated class DateUtils {
- method public static java.lang.String formatDate(java.util.Date);
- method public static java.lang.String formatDate(java.util.Date, java.lang.String);
- method public static java.util.Date parseDate(java.lang.String) throws org.apache.http.impl.cookie.DateParseException;
- method public static java.util.Date parseDate(java.lang.String, java.lang.String[]) throws org.apache.http.impl.cookie.DateParseException;
- method public static java.util.Date parseDate(java.lang.String, java.lang.String[], java.util.Date) throws org.apache.http.impl.cookie.DateParseException;
- field public static final java.util.TimeZone GMT;
- field public static final java.lang.String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
- field public static final java.lang.String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
- field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
- }
-
- public deprecated class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler {
- ctor public NetscapeDomainHandler();
- }
-
- public deprecated class NetscapeDraftHeaderParser {
- ctor public NetscapeDraftHeaderParser();
- method public org.apache.http.HeaderElement parseHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- field public static final org.apache.http.impl.cookie.NetscapeDraftHeaderParser DEFAULT;
- }
-
- public deprecated class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public NetscapeDraftSpec(java.lang.String[]);
- ctor public NetscapeDraftSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- field protected static final java.lang.String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
- }
-
- public deprecated class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public NetscapeDraftSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2109DomainHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public RFC2109Spec(java.lang.String[], boolean);
- ctor public RFC2109Spec();
- method protected void formatCookieAsVer(org.apache.http.util.CharArrayBuffer, org.apache.http.cookie.Cookie, int);
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method protected void formatParamAsVer(org.apache.http.util.CharArrayBuffer, java.lang.String, java.lang.String, int);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public RFC2109SpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public RFC2109VersionHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965CommentUrlAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965DiscardAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965DomainAttributeHandler();
- method public boolean domainMatch(java.lang.String, java.lang.String);
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965PortAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec {
- ctor public RFC2965Spec();
- ctor public RFC2965Spec(java.lang.String[], boolean);
- }
-
- public deprecated class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public RFC2965SpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965VersionAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
-}
-
-package org.apache.http.impl.entity {
-
- public deprecated class EntityDeserializer {
- ctor public EntityDeserializer(org.apache.http.entity.ContentLengthStrategy);
- method public org.apache.http.HttpEntity deserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.entity.BasicHttpEntity doDeserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class EntitySerializer {
- ctor public EntitySerializer(org.apache.http.entity.ContentLengthStrategy);
- method protected java.io.OutputStream doSerialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method public void serialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage, org.apache.http.HttpEntity) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
- ctor public LaxContentLengthStrategy();
- method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- }
-
- public deprecated class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
- ctor public StrictContentLengthStrategy();
- method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- }
-
-}
-
-package org.apache.http.impl.io {
-
- public abstract deprecated class AbstractMessageParser implements org.apache.http.io.HttpMessageParser {
- ctor public AbstractMessageParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.params.HttpParams);
- method public org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
- method protected abstract org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- method public static org.apache.http.Header[] parseHeaders(org.apache.http.io.SessionInputBuffer, int, int, org.apache.http.message.LineParser) throws org.apache.http.HttpException, java.io.IOException;
- field protected final org.apache.http.message.LineParser lineParser;
- }
-
- public abstract deprecated class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter {
- ctor public AbstractMessageWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method public void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method protected abstract void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- field protected final org.apache.http.util.CharArrayBuffer lineBuf;
- field protected final org.apache.http.message.LineFormatter lineFormatter;
- field protected final org.apache.http.io.SessionOutputBuffer sessionBuffer;
- }
-
- public abstract deprecated class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
- ctor public AbstractSessionInputBuffer();
- method protected int fillBuffer() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method protected boolean hasBufferedData();
- method protected void init(java.io.InputStream, int, org.apache.http.params.HttpParams);
- method public int read() throws java.io.IOException;
- method public int read(byte[], int, int) throws java.io.IOException;
- method public int read(byte[]) throws java.io.IOException;
- method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public java.lang.String readLine() throws java.io.IOException;
- }
-
- public abstract deprecated class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
- ctor public AbstractSessionOutputBuffer();
- method public void flush() throws java.io.IOException;
- method protected void flushBuffer() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method protected void init(java.io.OutputStream, int, org.apache.http.params.HttpParams);
- method public void write(byte[], int, int) throws java.io.IOException;
- method public void write(byte[]) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method public void writeLine(java.lang.String) throws java.io.IOException;
- method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
- public deprecated class ChunkedInputStream extends java.io.InputStream {
- ctor public ChunkedInputStream(org.apache.http.io.SessionInputBuffer);
- method public org.apache.http.Header[] getFooters();
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class ChunkedOutputStream extends java.io.OutputStream {
- ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer, int) throws java.io.IOException;
- ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer) throws java.io.IOException;
- method public void finish() throws java.io.IOException;
- method protected void flushCache() throws java.io.IOException;
- method protected void flushCacheWithAppend(byte[], int, int) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method protected void writeClosingChunk() throws java.io.IOException;
- }
-
- public deprecated class ContentLengthInputStream extends java.io.InputStream {
- ctor public ContentLengthInputStream(org.apache.http.io.SessionInputBuffer, long);
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class ContentLengthOutputStream extends java.io.OutputStream {
- ctor public ContentLengthOutputStream(org.apache.http.io.SessionOutputBuffer, long);
- method public void write(int) throws java.io.IOException;
- }
-
- public deprecated class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public HttpRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- }
-
- public deprecated class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter {
- ctor public HttpRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- }
-
- public deprecated class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public HttpResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- }
-
- public deprecated class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter {
- ctor public HttpResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- }
-
- public deprecated class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics {
- ctor public HttpTransportMetricsImpl();
- method public long getBytesTransferred();
- method public void incrementBytesTransferred(long);
- method public void reset();
- method public void setBytesTransferred(long);
- }
-
- public deprecated class IdentityInputStream extends java.io.InputStream {
- ctor public IdentityInputStream(org.apache.http.io.SessionInputBuffer);
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class IdentityOutputStream extends java.io.OutputStream {
- ctor public IdentityOutputStream(org.apache.http.io.SessionOutputBuffer);
- method public void write(int) throws java.io.IOException;
- }
-
- public deprecated class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer {
- ctor public SocketInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public boolean isDataAvailable(int) throws java.io.IOException;
- }
-
- public deprecated class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer {
- ctor public SocketOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.io {
-
- public abstract deprecated interface HttpMessageParser {
- method public abstract org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpMessageWriter {
- method public abstract void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpTransportMetrics {
- method public abstract long getBytesTransferred();
- method public abstract void reset();
- }
-
- public abstract deprecated interface SessionInputBuffer {
- method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
- method public abstract boolean isDataAvailable(int) throws java.io.IOException;
- method public abstract int read(byte[], int, int) throws java.io.IOException;
- method public abstract int read(byte[]) throws java.io.IOException;
- method public abstract int read() throws java.io.IOException;
- method public abstract int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public abstract java.lang.String readLine() throws java.io.IOException;
- }
-
- public abstract deprecated interface SessionOutputBuffer {
- method public abstract void flush() throws java.io.IOException;
- method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
- method public abstract void write(byte[], int, int) throws java.io.IOException;
- method public abstract void write(byte[]) throws java.io.IOException;
- method public abstract void write(int) throws java.io.IOException;
- method public abstract void writeLine(java.lang.String) throws java.io.IOException;
- method public abstract void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.message {
-
- public abstract deprecated class AbstractHttpMessage implements org.apache.http.HttpMessage {
- ctor protected AbstractHttpMessage(org.apache.http.params.HttpParams);
- ctor protected AbstractHttpMessage();
- method public void addHeader(org.apache.http.Header);
- method public void addHeader(java.lang.String, java.lang.String);
- method public boolean containsHeader(java.lang.String);
- method public org.apache.http.Header[] getAllHeaders();
- method public org.apache.http.Header getFirstHeader(java.lang.String);
- method public org.apache.http.Header[] getHeaders(java.lang.String);
- method public org.apache.http.Header getLastHeader(java.lang.String);
- method public org.apache.http.params.HttpParams getParams();
- method public org.apache.http.HeaderIterator headerIterator();
- method public org.apache.http.HeaderIterator headerIterator(java.lang.String);
- method public void removeHeader(org.apache.http.Header);
- method public void removeHeaders(java.lang.String);
- method public void setHeader(org.apache.http.Header);
- method public void setHeader(java.lang.String, java.lang.String);
- method public void setHeaders(org.apache.http.Header[]);
- method public void setParams(org.apache.http.params.HttpParams);
- field protected org.apache.http.message.HeaderGroup headergroup;
- field protected org.apache.http.params.HttpParams params;
- }
-
- public deprecated class BasicHeader implements java.lang.Cloneable org.apache.http.Header {
- ctor public BasicHeader(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement {
- ctor public BasicHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
- ctor public BasicHeaderElement(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getName();
- method public org.apache.http.NameValuePair getParameter(int);
- method public org.apache.http.NameValuePair getParameterByName(java.lang.String);
- method public int getParameterCount();
- method public org.apache.http.NameValuePair[] getParameters();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator {
- ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator, org.apache.http.message.HeaderValueParser);
- ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.HeaderElement nextElement() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- }
-
- public deprecated class BasicHeaderIterator implements org.apache.http.HeaderIterator {
- ctor public BasicHeaderIterator(org.apache.http.Header[], java.lang.String);
- method protected boolean filterHeader(int);
- method protected int findNext(int);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- field protected final org.apache.http.Header[] allHeaders;
- field protected int currentIndex;
- field protected java.lang.String headerName;
- }
-
- public deprecated class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter {
- ctor public BasicHeaderValueFormatter();
- method protected void doFormatValue(org.apache.http.util.CharArrayBuffer, java.lang.String, boolean);
- method protected int estimateElementsLen(org.apache.http.HeaderElement[]);
- method protected int estimateHeaderElementLen(org.apache.http.HeaderElement);
- method protected int estimateNameValuePairLen(org.apache.http.NameValuePair);
- method protected int estimateParametersLen(org.apache.http.NameValuePair[]);
- method public static final java.lang.String formatElements(org.apache.http.HeaderElement[], boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
- method public static final java.lang.String formatHeaderElement(org.apache.http.HeaderElement, boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
- method public static final java.lang.String formatNameValuePair(org.apache.http.NameValuePair, boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
- method public static final java.lang.String formatParameters(org.apache.http.NameValuePair[], boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
- method protected boolean isSeparator(char);
- method protected boolean isUnsafe(char);
- field public static final org.apache.http.message.BasicHeaderValueFormatter DEFAULT;
- field public static final java.lang.String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
- field public static final java.lang.String UNSAFE_CHARS = "\"\\";
- }
-
- public deprecated class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser {
- ctor public BasicHeaderValueParser();
- method protected org.apache.http.HeaderElement createHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
- method protected org.apache.http.NameValuePair createNameValuePair(java.lang.String, java.lang.String);
- method public static final org.apache.http.HeaderElement[] parseElements(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.HeaderElement parseHeaderElement(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.NameValuePair parseNameValuePair(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor, char[]);
- method public static final org.apache.http.NameValuePair[] parseParameters(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- field public static final org.apache.http.message.BasicHeaderValueParser DEFAULT;
- }
-
- public deprecated class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String);
- ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- ctor public BasicHttpEntityEnclosingRequest(org.apache.http.RequestLine);
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest {
- ctor public BasicHttpRequest(java.lang.String, java.lang.String);
- ctor public BasicHttpRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- ctor public BasicHttpRequest(org.apache.http.RequestLine);
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- }
-
- public deprecated class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse {
- ctor public BasicHttpResponse(org.apache.http.StatusLine, org.apache.http.ReasonPhraseCatalog, java.util.Locale);
- ctor public BasicHttpResponse(org.apache.http.StatusLine);
- ctor public BasicHttpResponse(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public org.apache.http.HttpEntity getEntity();
- method public java.util.Locale getLocale();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method protected java.lang.String getReason(int);
- method public org.apache.http.StatusLine getStatusLine();
- method public void setEntity(org.apache.http.HttpEntity);
- method public void setLocale(java.util.Locale);
- method public void setReasonPhrase(java.lang.String);
- method public void setStatusCode(int);
- method public void setStatusLine(org.apache.http.StatusLine);
- method public void setStatusLine(org.apache.http.ProtocolVersion, int);
- method public void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- }
-
- public deprecated class BasicLineFormatter implements org.apache.http.message.LineFormatter {
- ctor public BasicLineFormatter();
- method public org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
- method protected void doFormatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method protected void doFormatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method protected void doFormatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- method protected int estimateProtocolVersionLen(org.apache.http.ProtocolVersion);
- method public static final java.lang.String formatHeader(org.apache.http.Header, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method public static final java.lang.String formatProtocolVersion(org.apache.http.ProtocolVersion, org.apache.http.message.LineFormatter);
- method public static final java.lang.String formatRequestLine(org.apache.http.RequestLine, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method public static final java.lang.String formatStatusLine(org.apache.http.StatusLine, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- method protected org.apache.http.util.CharArrayBuffer initBuffer(org.apache.http.util.CharArrayBuffer);
- field public static final org.apache.http.message.BasicLineFormatter DEFAULT;
- }
-
- public deprecated class BasicLineParser implements org.apache.http.message.LineParser {
- ctor public BasicLineParser(org.apache.http.ProtocolVersion);
- ctor public BasicLineParser();
- method protected org.apache.http.ProtocolVersion createProtocolVersion(int, int);
- method protected org.apache.http.RequestLine createRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- method protected org.apache.http.StatusLine createStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.Header parseHeader(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public static final org.apache.http.ProtocolVersion parseProtocolVersion(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public static final org.apache.http.RequestLine parseRequestLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public static final org.apache.http.StatusLine parseStatusLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method protected void skipWhitespace(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- field public static final org.apache.http.message.BasicLineParser DEFAULT;
- field protected final org.apache.http.ProtocolVersion protocol;
- }
-
- public deprecated class BasicListHeaderIterator implements org.apache.http.HeaderIterator {
- ctor public BasicListHeaderIterator(java.util.List, java.lang.String);
- method protected boolean filterHeader(int);
- method protected int findNext(int);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- field protected final java.util.List allHeaders;
- field protected int currentIndex;
- field protected java.lang.String headerName;
- field protected int lastIndex;
- }
-
- public deprecated class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair {
- ctor public BasicNameValuePair(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine {
- ctor public BasicRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getMethod();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public java.lang.String getUri();
- }
-
- public deprecated class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine {
- ctor public BasicStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public java.lang.String getReasonPhrase();
- method public int getStatusCode();
- }
-
- public deprecated class BasicTokenIterator implements org.apache.http.TokenIterator {
- ctor public BasicTokenIterator(org.apache.http.HeaderIterator);
- method protected java.lang.String createToken(java.lang.String, int, int);
- method protected int findNext(int) throws org.apache.http.ParseException;
- method protected int findTokenEnd(int);
- method protected int findTokenSeparator(int);
- method protected int findTokenStart(int);
- method public boolean hasNext();
- method protected boolean isHttpSeparator(char);
- method protected boolean isTokenChar(char);
- method protected boolean isTokenSeparator(char);
- method protected boolean isWhitespace(char);
- method public final java.lang.Object next() throws java.util.NoSuchElementException, org.apache.http.ParseException;
- method public java.lang.String nextToken() throws java.util.NoSuchElementException, org.apache.http.ParseException;
- method public final void remove() throws java.lang.UnsupportedOperationException;
- field public static final java.lang.String HTTP_SEPARATORS = " ,;=()<>@:\\\"/[]?{}\t";
- field protected java.lang.String currentHeader;
- field protected java.lang.String currentToken;
- field protected final org.apache.http.HeaderIterator headerIt;
- field protected int searchPos;
- }
-
- public deprecated class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader {
- ctor public BufferedHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.util.CharArrayBuffer getBuffer();
- method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- method public int getValuePos();
- }
-
- public deprecated class HeaderGroup implements java.lang.Cloneable {
- ctor public HeaderGroup();
- method public void addHeader(org.apache.http.Header);
- method public void clear();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public boolean containsHeader(java.lang.String);
- method public org.apache.http.message.HeaderGroup copy();
- method public org.apache.http.Header[] getAllHeaders();
- method public org.apache.http.Header getCondensedHeader(java.lang.String);
- method public org.apache.http.Header getFirstHeader(java.lang.String);
- method public org.apache.http.Header[] getHeaders(java.lang.String);
- method public org.apache.http.Header getLastHeader(java.lang.String);
- method public org.apache.http.HeaderIterator iterator();
- method public org.apache.http.HeaderIterator iterator(java.lang.String);
- method public void removeHeader(org.apache.http.Header);
- method public void setHeaders(org.apache.http.Header[]);
- method public void updateHeader(org.apache.http.Header);
- }
-
- public abstract deprecated interface HeaderValueFormatter {
- method public abstract org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
- }
-
- public abstract deprecated interface HeaderValueParser {
- method public abstract org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- }
-
- public abstract deprecated interface LineFormatter {
- method public abstract org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
- method public abstract org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method public abstract org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method public abstract org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- }
-
- public abstract deprecated interface LineParser {
- method public abstract boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public abstract org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public abstract org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- }
-
- public deprecated class ParserCursor {
- ctor public ParserCursor(int, int);
- method public boolean atEnd();
- method public int getLowerBound();
- method public int getPos();
- method public int getUpperBound();
- method public void updatePos(int);
- }
-
-}
-
package org.apache.http.params {
- public abstract deprecated class AbstractHttpParams implements org.apache.http.params.HttpParams {
- ctor protected AbstractHttpParams();
- method public boolean getBooleanParameter(java.lang.String, boolean);
- method public double getDoubleParameter(java.lang.String, double);
- method public int getIntParameter(java.lang.String, int);
- method public long getLongParameter(java.lang.String, long);
- method public boolean isParameterFalse(java.lang.String);
- method public boolean isParameterTrue(java.lang.String);
- method public org.apache.http.params.HttpParams setBooleanParameter(java.lang.String, boolean);
- method public org.apache.http.params.HttpParams setDoubleParameter(java.lang.String, double);
- method public org.apache.http.params.HttpParams setIntParameter(java.lang.String, int);
- method public org.apache.http.params.HttpParams setLongParameter(java.lang.String, long);
- }
-
- public final deprecated class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable {
- ctor public BasicHttpParams();
- method public void clear();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.params.HttpParams copy();
- method protected void copyParams(org.apache.http.params.HttpParams);
- method public java.lang.Object getParameter(java.lang.String);
- method public boolean isParameterSet(java.lang.String);
- method public boolean isParameterSetLocally(java.lang.String);
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
- method public void setParameters(java.lang.String[], java.lang.Object);
- }
-
public abstract deprecated interface CoreConnectionPNames {
field public static final java.lang.String CONNECTION_TIMEOUT = "http.connection.timeout";
field public static final java.lang.String MAX_HEADER_COUNT = "http.connection.max-header-count";
@@ -57899,41 +54977,6 @@
field public static final java.lang.String TCP_NODELAY = "http.tcp.nodelay";
}
- public abstract deprecated interface CoreProtocolPNames {
- field public static final java.lang.String HTTP_CONTENT_CHARSET = "http.protocol.content-charset";
- field public static final java.lang.String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
- field public static final java.lang.String ORIGIN_SERVER = "http.origin-server";
- field public static final java.lang.String PROTOCOL_VERSION = "http.protocol.version";
- field public static final java.lang.String STRICT_TRANSFER_ENCODING = "http.protocol.strict-transfer-encoding";
- field public static final java.lang.String USER_AGENT = "http.useragent";
- field public static final java.lang.String USE_EXPECT_CONTINUE = "http.protocol.expect-continue";
- field public static final java.lang.String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
- }
-
- public final deprecated class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams {
- ctor public DefaultedHttpParams(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- method public org.apache.http.params.HttpParams copy();
- method public org.apache.http.params.HttpParams getDefaults();
- method public java.lang.Object getParameter(java.lang.String);
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
- }
-
- public abstract deprecated class HttpAbstractParamBean {
- ctor public HttpAbstractParamBean(org.apache.http.params.HttpParams);
- field protected final org.apache.http.params.HttpParams params;
- }
-
- public deprecated class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public HttpConnectionParamBean(org.apache.http.params.HttpParams);
- method public void setConnectionTimeout(int);
- method public void setLinger(int);
- method public void setSoTimeout(int);
- method public void setSocketBufferSize(int);
- method public void setStaleCheckingEnabled(boolean);
- method public void setTcpNoDelay(boolean);
- }
-
public final deprecated class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames {
method public static int getConnectionTimeout(org.apache.http.params.HttpParams);
method public static int getLinger(org.apache.http.params.HttpParams);
@@ -57966,359 +55009,6 @@
method public abstract org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
}
- public deprecated class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public HttpProtocolParamBean(org.apache.http.params.HttpParams);
- method public void setContentCharset(java.lang.String);
- method public void setHttpElementCharset(java.lang.String);
- method public void setUseExpectContinue(boolean);
- method public void setUserAgent(java.lang.String);
- method public void setVersion(org.apache.http.HttpVersion);
- }
-
- public final deprecated class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames {
- method public static java.lang.String getContentCharset(org.apache.http.params.HttpParams);
- method public static java.lang.String getHttpElementCharset(org.apache.http.params.HttpParams);
- method public static java.lang.String getUserAgent(org.apache.http.params.HttpParams);
- method public static org.apache.http.ProtocolVersion getVersion(org.apache.http.params.HttpParams);
- method public static void setContentCharset(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setHttpElementCharset(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setUseExpectContinue(org.apache.http.params.HttpParams, boolean);
- method public static void setUserAgent(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setVersion(org.apache.http.params.HttpParams, org.apache.http.ProtocolVersion);
- method public static boolean useExpectContinue(org.apache.http.params.HttpParams);
- }
-
-}
-
-package org.apache.http.protocol {
-
- public deprecated class BasicHttpContext implements org.apache.http.protocol.HttpContext {
- ctor public BasicHttpContext();
- ctor public BasicHttpContext(org.apache.http.protocol.HttpContext);
- method public java.lang.Object getAttribute(java.lang.String);
- method public java.lang.Object removeAttribute(java.lang.String);
- method public void setAttribute(java.lang.String, java.lang.Object);
- }
-
- public final deprecated class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList {
- ctor public BasicHttpProcessor();
- method public final void addInterceptor(org.apache.http.HttpRequestInterceptor);
- method public final void addInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public final void addInterceptor(org.apache.http.HttpResponseInterceptor);
- method public final void addInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public void clearInterceptors();
- method public void clearRequestInterceptors();
- method public void clearResponseInterceptors();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.protocol.BasicHttpProcessor copy();
- method protected void copyInterceptors(org.apache.http.protocol.BasicHttpProcessor);
- method public org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public int getRequestInterceptorCount();
- method public org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public int getResponseInterceptorCount();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void removeRequestInterceptorByClass(java.lang.Class);
- method public void removeResponseInterceptorByClass(java.lang.Class);
- method public void setInterceptors(java.util.List);
- field protected java.util.List requestInterceptors;
- field protected java.util.List responseInterceptors;
- }
-
- public final deprecated class DefaultedHttpContext implements org.apache.http.protocol.HttpContext {
- ctor public DefaultedHttpContext(org.apache.http.protocol.HttpContext, org.apache.http.protocol.HttpContext);
- method public java.lang.Object getAttribute(java.lang.String);
- method public org.apache.http.protocol.HttpContext getDefaults();
- method public java.lang.Object removeAttribute(java.lang.String);
- method public void setAttribute(java.lang.String, java.lang.Object);
- }
-
- public abstract deprecated interface ExecutionContext {
- field public static final java.lang.String HTTP_CONNECTION = "http.connection";
- field public static final java.lang.String HTTP_PROXY_HOST = "http.proxy_host";
- field public static final java.lang.String HTTP_REQUEST = "http.request";
- field public static final java.lang.String HTTP_REQ_SENT = "http.request_sent";
- field public static final java.lang.String HTTP_RESPONSE = "http.response";
- field public static final java.lang.String HTTP_TARGET_HOST = "http.target_host";
- }
-
- public final deprecated class HTTP {
- method public static boolean isWhitespace(char);
- field public static final java.lang.String ASCII = "ASCII";
- field public static final java.lang.String CHARSET_PARAM = "; charset=";
- field public static final java.lang.String CHUNK_CODING = "chunked";
- field public static final java.lang.String CONN_CLOSE = "Close";
- field public static final java.lang.String CONN_DIRECTIVE = "Connection";
- field public static final java.lang.String CONN_KEEP_ALIVE = "Keep-Alive";
- field public static final java.lang.String CONTENT_ENCODING = "Content-Encoding";
- field public static final java.lang.String CONTENT_LEN = "Content-Length";
- field public static final java.lang.String CONTENT_TYPE = "Content-Type";
- field public static final int CR = 13; // 0xd
- field public static final java.lang.String DATE_HEADER = "Date";
- field public static final java.lang.String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
- field public static final java.lang.String DEFAULT_CONTENT_TYPE = "application/octet-stream";
- field public static final java.lang.String DEFAULT_PROTOCOL_CHARSET = "US-ASCII";
- field public static final java.lang.String EXPECT_CONTINUE = "100-continue";
- field public static final java.lang.String EXPECT_DIRECTIVE = "Expect";
- field public static final int HT = 9; // 0x9
- field public static final java.lang.String IDENTITY_CODING = "identity";
- field public static final java.lang.String ISO_8859_1 = "ISO-8859-1";
- field public static final int LF = 10; // 0xa
- field public static final java.lang.String OCTET_STREAM_TYPE = "application/octet-stream";
- field public static final java.lang.String PLAIN_TEXT_TYPE = "text/plain";
- field public static final java.lang.String SERVER_HEADER = "Server";
- field public static final int SP = 32; // 0x20
- field public static final java.lang.String TARGET_HOST = "Host";
- field public static final java.lang.String TRANSFER_ENCODING = "Transfer-Encoding";
- field public static final java.lang.String USER_AGENT = "User-Agent";
- field public static final java.lang.String US_ASCII = "US-ASCII";
- field public static final java.lang.String UTF_16 = "UTF-16";
- field public static final java.lang.String UTF_8 = "UTF-8";
- }
-
- public abstract deprecated interface HttpContext {
- method public abstract java.lang.Object getAttribute(java.lang.String);
- method public abstract java.lang.Object removeAttribute(java.lang.String);
- method public abstract void setAttribute(java.lang.String, java.lang.Object);
- field public static final java.lang.String RESERVED_PREFIX = "http.";
- }
-
- public deprecated class HttpDateGenerator {
- ctor public HttpDateGenerator();
- method public synchronized java.lang.String getCurrentDate();
- field public static final java.util.TimeZone GMT;
- field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
- }
-
- public abstract deprecated interface HttpExpectationVerifier {
- method public abstract void verify(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- }
-
- public abstract deprecated interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor {
- }
-
- public deprecated class HttpRequestExecutor {
- ctor public HttpRequestExecutor();
- method protected boolean canResponseHaveBody(org.apache.http.HttpRequest, org.apache.http.HttpResponse);
- method protected org.apache.http.HttpResponse doReceiveResponse(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.HttpResponse doSendRequest(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void postProcess(org.apache.http.HttpResponse, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void preProcess(org.apache.http.HttpRequest, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpRequestHandler {
- method public abstract void handle(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver {
- ctor public HttpRequestHandlerRegistry();
- method public org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
- method protected deprecated boolean matchUriRequestPattern(java.lang.String, java.lang.String);
- method public void register(java.lang.String, org.apache.http.protocol.HttpRequestHandler);
- method public void setHandlers(java.util.Map);
- method public void unregister(java.lang.String);
- }
-
- public abstract deprecated interface HttpRequestHandlerResolver {
- method public abstract org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
- }
-
- public abstract deprecated interface HttpRequestInterceptorList {
- method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public abstract void clearRequestInterceptors();
- method public abstract org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public abstract int getRequestInterceptorCount();
- method public abstract void removeRequestInterceptorByClass(java.lang.Class);
- method public abstract void setInterceptors(java.util.List);
- }
-
- public abstract deprecated interface HttpResponseInterceptorList {
- method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public abstract void clearResponseInterceptors();
- method public abstract org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public abstract int getResponseInterceptorCount();
- method public abstract void removeResponseInterceptorByClass(java.lang.Class);
- method public abstract void setInterceptors(java.util.List);
- }
-
- public deprecated class HttpService {
- ctor public HttpService(org.apache.http.protocol.HttpProcessor, org.apache.http.ConnectionReuseStrategy, org.apache.http.HttpResponseFactory);
- method protected void doService(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.params.HttpParams getParams();
- method protected void handleException(org.apache.http.HttpException, org.apache.http.HttpResponse);
- method public void handleRequest(org.apache.http.HttpServerConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void setConnReuseStrategy(org.apache.http.ConnectionReuseStrategy);
- method public void setExpectationVerifier(org.apache.http.protocol.HttpExpectationVerifier);
- method public void setHandlerResolver(org.apache.http.protocol.HttpRequestHandlerResolver);
- method public void setHttpProcessor(org.apache.http.protocol.HttpProcessor);
- method public void setParams(org.apache.http.params.HttpParams);
- method public void setResponseFactory(org.apache.http.HttpResponseFactory);
- }
-
- public deprecated class RequestConnControl implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestConnControl();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestContent implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestContent();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestDate implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestDate();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestExpectContinue();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestTargetHost implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestTargetHost();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestUserAgent implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestUserAgent();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseConnControl implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseConnControl();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseContent implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseContent();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseDate implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseDate();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseServer implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseServer();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext {
- ctor public SyncBasicHttpContext(org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class UriPatternMatcher {
- ctor public UriPatternMatcher();
- method public java.lang.Object lookup(java.lang.String);
- method protected boolean matchUriRequestPattern(java.lang.String, java.lang.String);
- method public void register(java.lang.String, java.lang.Object);
- method public void setHandlers(java.util.Map);
- method public void unregister(java.lang.String);
- }
-
-}
-
-package org.apache.http.util {
-
- public final deprecated class ByteArrayBuffer {
- ctor public ByteArrayBuffer(int);
- method public void append(byte[], int, int);
- method public void append(int);
- method public void append(char[], int, int);
- method public void append(org.apache.http.util.CharArrayBuffer, int, int);
- method public byte[] buffer();
- method public int byteAt(int);
- method public int capacity();
- method public void clear();
- method public boolean isEmpty();
- method public boolean isFull();
- method public int length();
- method public void setLength(int);
- method public byte[] toByteArray();
- }
-
- public final deprecated class CharArrayBuffer {
- ctor public CharArrayBuffer(int);
- method public void append(char[], int, int);
- method public void append(java.lang.String);
- method public void append(org.apache.http.util.CharArrayBuffer, int, int);
- method public void append(org.apache.http.util.CharArrayBuffer);
- method public void append(char);
- method public void append(byte[], int, int);
- method public void append(org.apache.http.util.ByteArrayBuffer, int, int);
- method public void append(java.lang.Object);
- method public char[] buffer();
- method public int capacity();
- method public char charAt(int);
- method public void clear();
- method public void ensureCapacity(int);
- method public int indexOf(int, int, int);
- method public int indexOf(int);
- method public boolean isEmpty();
- method public boolean isFull();
- method public int length();
- method public void setLength(int);
- method public java.lang.String substring(int, int);
- method public java.lang.String substringTrimmed(int, int);
- method public char[] toCharArray();
- }
-
- public final deprecated class EncodingUtils {
- method public static byte[] getAsciiBytes(java.lang.String);
- method public static java.lang.String getAsciiString(byte[], int, int);
- method public static java.lang.String getAsciiString(byte[]);
- method public static byte[] getBytes(java.lang.String, java.lang.String);
- method public static java.lang.String getString(byte[], int, int, java.lang.String);
- method public static java.lang.String getString(byte[], java.lang.String);
- }
-
- public final deprecated class EntityUtils {
- method public static java.lang.String getContentCharSet(org.apache.http.HttpEntity) throws org.apache.http.ParseException;
- method public static byte[] toByteArray(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static java.lang.String toString(org.apache.http.HttpEntity, java.lang.String) throws java.io.IOException, org.apache.http.ParseException;
- method public static java.lang.String toString(org.apache.http.HttpEntity) throws java.io.IOException, org.apache.http.ParseException;
- }
-
- public final deprecated class ExceptionUtils {
- method public static void initCause(java.lang.Throwable, java.lang.Throwable);
- }
-
- public final deprecated class LangUtils {
- method public static boolean equals(java.lang.Object, java.lang.Object);
- method public static boolean equals(java.lang.Object[], java.lang.Object[]);
- method public static int hashCode(int, int);
- method public static int hashCode(int, boolean);
- method public static int hashCode(int, java.lang.Object);
- field public static final int HASH_OFFSET = 37; // 0x25
- field public static final int HASH_SEED = 17; // 0x11
- }
-
- public deprecated class VersionInfo {
- ctor protected VersionInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- method protected static final org.apache.http.util.VersionInfo fromMap(java.lang.String, java.util.Map, java.lang.ClassLoader);
- method public final java.lang.String getClassloader();
- method public final java.lang.String getModule();
- method public final java.lang.String getPackage();
- method public final java.lang.String getRelease();
- method public final java.lang.String getTimestamp();
- method public static final org.apache.http.util.VersionInfo[] loadVersionInfo(java.lang.String[], java.lang.ClassLoader);
- method public static final org.apache.http.util.VersionInfo loadVersionInfo(java.lang.String, java.lang.ClassLoader);
- field public static final java.lang.String PROPERTY_MODULE = "info.module";
- field public static final java.lang.String PROPERTY_RELEASE = "info.release";
- field public static final java.lang.String PROPERTY_TIMESTAMP = "info.timestamp";
- field public static final java.lang.String UNAVAILABLE = "UNAVAILABLE";
- field public static final java.lang.String VERSION_PROPERTY_FILE = "version.properties";
- }
-
}
package org.json {
diff --git a/api/system-current.txt b/api/system-current.txt
index ce68ca9..b2e44a3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -958,6 +958,7 @@
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
+ field public static final int numbersInnerTextColor = 16843999; // 0x10104df
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
field public static final int numbersTextColor = 16843937; // 0x10104a1
field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -1785,8 +1786,10 @@
field public static final int message = 16908299; // 0x102000b
field public static final int navigationBarBackground = 16908336; // 0x1020030
field public static final int paste = 16908322; // 0x1020022
+ field public static final int pasteAsPlainText = 16908339; // 0x1020033
field public static final int primary = 16908300; // 0x102000c
field public static final int progress = 16908301; // 0x102000d
+ field public static final int redo = 16908338; // 0x1020032
field public static final int secondaryProgress = 16908303; // 0x102000f
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
@@ -1803,6 +1806,7 @@
field public static final int text2 = 16908309; // 0x1020015
field public static final int title = 16908310; // 0x1020016
field public static final int toggle = 16908311; // 0x1020017
+ field public static final int undo = 16908337; // 0x1020031
field public static final int widget_frame = 16908312; // 0x1020018
}
@@ -2165,6 +2169,21 @@
field public static final int Theme_Light_Panel = 16973914; // 0x103005a
field public static final int Theme_Light_WallpaperSettings = 16973922; // 0x1030062
field public static final int Theme_Material = 16974372; // 0x1030224
+ field public static final int Theme_Material_DayNight = 16974548; // 0x10302d4
+ field public static final int Theme_Material_DayNight_DarkActionBar = 16974549; // 0x10302d5
+ field public static final int Theme_Material_DayNight_Dialog = 16974550; // 0x10302d6
+ field public static final int Theme_Material_DayNight_DialogWhenLarge = 16974556; // 0x10302dc
+ field public static final int Theme_Material_DayNight_DialogWhenLarge_NoActionBar = 16974557; // 0x10302dd
+ field public static final int Theme_Material_DayNight_Dialog_Alert = 16974551; // 0x10302d7
+ field public static final int Theme_Material_DayNight_Dialog_MinWidth = 16974552; // 0x10302d8
+ field public static final int Theme_Material_DayNight_Dialog_NoActionBar = 16974553; // 0x10302d9
+ field public static final int Theme_Material_DayNight_Dialog_NoActionBar_MinWidth = 16974554; // 0x10302da
+ field public static final int Theme_Material_DayNight_Dialog_Presentation = 16974555; // 0x10302db
+ field public static final int Theme_Material_DayNight_NoActionBar = 16974558; // 0x10302de
+ field public static final int Theme_Material_DayNight_NoActionBar_Fullscreen = 16974559; // 0x10302df
+ field public static final int Theme_Material_DayNight_NoActionBar_Overscan = 16974560; // 0x10302e0
+ field public static final int Theme_Material_DayNight_NoActionBar_TranslucentDecor = 16974561; // 0x10302e1
+ field public static final int Theme_Material_DayNight_Panel = 16974562; // 0x10302e2
field public static final int Theme_Material_Dialog = 16974373; // 0x1030225
field public static final int Theme_Material_DialogWhenLarge = 16974379; // 0x103022b
field public static final int Theme_Material_DialogWhenLarge_NoActionBar = 16974380; // 0x103022c
@@ -2184,6 +2203,7 @@
field public static final int Theme_Material_Light_Dialog_NoActionBar = 16974396; // 0x103023c
field public static final int Theme_Material_Light_Dialog_NoActionBar_MinWidth = 16974397; // 0x103023d
field public static final int Theme_Material_Light_Dialog_Presentation = 16974398; // 0x103023e
+ field public static final int Theme_Material_Light_LightStatusBar = 16974563; // 0x10302e3
field public static final int Theme_Material_Light_NoActionBar = 16974401; // 0x1030241
field public static final int Theme_Material_Light_NoActionBar_Fullscreen = 16974402; // 0x1030242
field public static final int Theme_Material_Light_NoActionBar_Overscan = 16974403; // 0x1030243
@@ -3769,6 +3789,7 @@
}
public class ActivityOptions {
+ method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
@@ -4012,6 +4033,7 @@
public final class AssistData implements android.os.Parcelable {
method public int describeContents();
+ method public android.content.ComponentName getActivityComponent();
method public static android.app.AssistData getAssistData(android.os.Bundle);
method public void getWindowAt(int, android.app.AssistData.ViewNode);
method public int getWindowCount();
@@ -5481,6 +5503,7 @@
ctor public DeviceAdminReceiver();
method public android.app.admin.DevicePolicyManager getManager(android.content.Context);
method public android.content.ComponentName getWho(android.content.Context);
+ method public java.lang.String onChoosePrivateKeyAlias(android.content.Context, android.content.Intent, int, java.lang.String, int, java.lang.String, java.lang.String);
method public java.lang.CharSequence onDisableRequested(android.content.Context, android.content.Intent);
method public void onDisabled(android.content.Context, android.content.Intent);
method public void onEnabled(android.content.Context, android.content.Intent);
@@ -5555,7 +5578,6 @@
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
- method public java.util.List<android.os.PersistableBundle> getTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName);
method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(android.content.ComponentName, int);
method public boolean installCaCert(android.content.ComponentName, byte[]);
@@ -5605,13 +5627,13 @@
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
- method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
+ field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
@@ -12048,15 +12070,8 @@
method public final void setTileModeY(android.graphics.Shader.TileMode);
}
- public class ClipDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class ClipDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public ClipDrawable(android.graphics.drawable.Drawable, int, int);
- method public void draw(android.graphics.Canvas);
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
field public static final int HORIZONTAL = 1; // 0x1
field public static final int VERTICAL = 2; // 0x2
}
@@ -12098,8 +12113,10 @@
method public android.graphics.Rect getDirtyBounds();
method public boolean getDither();
method public boolean getFilterBitmap();
+ method public void getHotspotBounds(android.graphics.Rect);
method public int getIntrinsicHeight();
method public int getIntrinsicWidth();
+ method public int getLayoutDirection();
method public final int getLevel();
method public int getMinimumHeight();
method public int getMinimumWidth();
@@ -12117,6 +12134,7 @@
method public void jumpToCurrentState();
method public android.graphics.drawable.Drawable mutate();
method protected void onBoundsChange(android.graphics.Rect);
+ method public boolean onLayoutDirectionChange(int);
method protected boolean onLevelChange(int);
method protected boolean onStateChange(int[]);
method public static int resolveOpacity(int, int);
@@ -12133,6 +12151,7 @@
method public void setFilterBitmap(boolean);
method public void setHotspot(float, float);
method public void setHotspotBounds(int, int, int, int);
+ method public final boolean setLayoutDirection(int);
method public final boolean setLevel(int);
method public boolean setState(int[]);
method public void setTint(int);
@@ -12197,6 +12216,19 @@
method public final void setVariablePadding(boolean);
}
+ public abstract class DrawableWrapper extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ ctor public DrawableWrapper(android.graphics.drawable.Drawable);
+ method public void draw(android.graphics.Canvas);
+ method public android.graphics.drawable.Drawable getDrawable();
+ method public int getOpacity();
+ method public void invalidateDrawable(android.graphics.drawable.Drawable);
+ method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
+ method public void setAlpha(int);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDrawable(android.graphics.drawable.Drawable);
+ method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+ }
+
public class GradientDrawable extends android.graphics.drawable.Drawable {
ctor public GradientDrawable();
ctor public GradientDrawable(android.graphics.drawable.GradientDrawable.Orientation, int[]);
@@ -12244,27 +12276,27 @@
enum_constant public static final android.graphics.drawable.GradientDrawable.Orientation TR_BL;
}
- public class InsetDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class InsetDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public InsetDrawable(android.graphics.drawable.Drawable, int);
ctor public InsetDrawable(android.graphics.drawable.Drawable, int, int, int, int);
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
public class LayerDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
ctor public LayerDrawable(android.graphics.drawable.Drawable[]);
+ method public int addLayer(android.graphics.drawable.Drawable);
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable findDrawableByLayerId(int);
+ method public int findIndexByLayerId(int);
method public android.graphics.drawable.Drawable getDrawable(int);
method public int getId(int);
method public int getLayerGravity(int);
method public int getLayerHeight(int);
+ method public int getLayerInsetBottom(int);
+ method public int getLayerInsetEnd(int);
+ method public int getLayerInsetLeft(int);
+ method public int getLayerInsetRight(int);
+ method public int getLayerInsetStart(int);
+ method public int getLayerInsetTop(int);
method public int getLayerWidth(int);
method public int getNumberOfLayers();
method public int getOpacity();
@@ -12273,12 +12305,21 @@
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
method public void setAlpha(int);
method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDrawable(int, android.graphics.drawable.Drawable);
method public boolean setDrawableByLayerId(int, android.graphics.drawable.Drawable);
method public void setId(int, int);
method public void setLayerGravity(int, int);
+ method public void setLayerHeight(int, int);
method public void setLayerInset(int, int, int, int, int);
+ method public void setLayerInsetBottom(int, int);
+ method public void setLayerInsetEnd(int, int);
+ method public void setLayerInsetLeft(int, int);
method public void setLayerInsetRelative(int, int, int, int, int);
+ method public void setLayerInsetRight(int, int);
+ method public void setLayerInsetStart(int, int);
+ method public void setLayerInsetTop(int, int);
method public void setLayerSize(int, int, int);
+ method public void setLayerWidth(int, int);
method public void setOpacity(int);
method public void setPaddingMode(int);
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
@@ -12325,44 +12366,30 @@
public class RippleDrawable extends android.graphics.drawable.LayerDrawable {
ctor public RippleDrawable(android.content.res.ColorStateList, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+ method public int getRadius();
method public void setColor(android.content.res.ColorStateList);
+ method public void setRadius(int);
+ field public static final int RADIUS_AUTO = -1; // 0xffffffff
}
- public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class RotateDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public RotateDrawable();
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
method public float getFromDegrees();
- method public int getOpacity();
method public float getPivotX();
method public float getPivotY();
method public float getToDegrees();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
method public boolean isPivotXRelative();
method public boolean isPivotYRelative();
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void setDrawable(android.graphics.drawable.Drawable);
method public void setFromDegrees(float);
method public void setPivotX(float);
method public void setPivotXRelative(boolean);
method public void setPivotY(float);
method public void setPivotYRelative(boolean);
method public void setToDegrees(float);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
- public class ScaleDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
+ public class ScaleDrawable extends android.graphics.drawable.DrawableWrapper {
ctor public ScaleDrawable(android.graphics.drawable.Drawable, int, float, float);
- method public void draw(android.graphics.Canvas);
- method public android.graphics.drawable.Drawable getDrawable();
- method public int getOpacity();
- method public void invalidateDrawable(android.graphics.drawable.Drawable);
- method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
}
public class ShapeDrawable extends android.graphics.drawable.Drawable {
@@ -15093,6 +15120,8 @@
field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
field public static final int FLAG_BEACON = 8; // 0x8
+ field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 64; // 0x40
+ field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
field public static final int FLAG_HW_HOTWORD = 32; // 0x20
field public static final int USAGE_ALARM = 4; // 0x4
@@ -19200,30 +19229,6 @@
package android.net.http {
- public final deprecated class AndroidHttpClient implements org.apache.http.client.HttpClient {
- method public void close();
- method public void disableCurlLogging();
- method public void enableCurlLogging(java.lang.String, int);
- method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public static org.apache.http.entity.AbstractHttpEntity getCompressedEntity(byte[], android.content.ContentResolver) throws java.io.IOException;
- method public org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public static long getMinGzipSize(android.content.ContentResolver);
- method public org.apache.http.params.HttpParams getParams();
- method public static java.io.InputStream getUngzippedContent(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static void modifyRequestToAcceptGzipResponse(org.apache.http.HttpRequest);
- method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context);
- method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String);
- method public static long parseDate(java.lang.String);
- field public static long DEFAULT_SYNC_MIN_GZIP_BYTES;
- }
-
public final class HttpResponseCache extends java.net.ResponseCache implements java.io.Closeable {
method public void close() throws java.io.IOException;
method public void delete() throws java.io.IOException;
@@ -28915,6 +28920,7 @@
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
+ method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String, java.lang.String);
method public static android.content.Intent createInstallIntent();
method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
@@ -29177,6 +29183,7 @@
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
+ field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
field public static final int TRIM_FULL = 0; // 0x0
field public static final int TRIM_LIGHT = 1; // 0x1
@@ -29337,9 +29344,10 @@
method public android.os.IBinder onBind(android.content.Intent);
method public void onReady();
method public void onShutdown();
- method public void startSession(android.os.Bundle);
+ method public void startSession(android.os.Bundle, int);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+ field public static final int START_WITH_ASSIST = 1; // 0x1
}
public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
@@ -29357,10 +29365,11 @@
method public void onCompleteVoice(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.CharSequence, android.os.Bundle);
- method public void onCreate(android.os.Bundle);
+ method public void onCreate(android.os.Bundle, int);
method public android.view.View onCreateContentView();
method public void onDestroy();
method public boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
+ method public void onHandleAssist(android.os.Bundle);
method public boolean onKeyDown(int, android.view.KeyEvent);
method public boolean onKeyLongPress(int, android.view.KeyEvent);
method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
@@ -30858,6 +30867,7 @@
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
@@ -33948,6 +33958,7 @@
method public android.transition.Transition addTarget(java.lang.String);
method public android.transition.Transition addTarget(java.lang.Class);
method public android.transition.Transition addTarget(android.view.View);
+ method protected boolean areValuesChanged(android.transition.TransitionValues, android.transition.TransitionValues);
method public boolean canRemoveViews();
method public abstract void captureEndValues(android.transition.TransitionValues);
method public abstract void captureStartValues(android.transition.TransitionValues);
@@ -34202,6 +34213,7 @@
method public boolean equals(android.util.DisplayMetrics);
method public void setTo(android.util.DisplayMetrics);
method public void setToDefaults();
+ field public static final int DENSITY_280 = 280; // 0x118
field public static final int DENSITY_400 = 400; // 0x190
field public static final int DENSITY_560 = 560; // 0x230
field public static final int DENSITY_DEFAULT = 160; // 0xa0
@@ -40242,6 +40254,7 @@
ctor public CompoundButton(android.content.Context, android.util.AttributeSet);
ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int);
ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int, int);
+ method public android.graphics.drawable.Drawable getButtonDrawable();
method public android.content.res.ColorStateList getButtonTintList();
method public android.graphics.PorterDuff.Mode getButtonTintMode();
method public boolean isChecked();
@@ -57322,1105 +57335,13 @@
}
-package org.apache.commons.logging {
-
- public abstract deprecated interface Log {
- method public abstract void debug(java.lang.Object);
- method public abstract void debug(java.lang.Object, java.lang.Throwable);
- method public abstract void error(java.lang.Object);
- method public abstract void error(java.lang.Object, java.lang.Throwable);
- method public abstract void fatal(java.lang.Object);
- method public abstract void fatal(java.lang.Object, java.lang.Throwable);
- method public abstract void info(java.lang.Object);
- method public abstract void info(java.lang.Object, java.lang.Throwable);
- method public abstract boolean isDebugEnabled();
- method public abstract boolean isErrorEnabled();
- method public abstract boolean isFatalEnabled();
- method public abstract boolean isInfoEnabled();
- method public abstract boolean isTraceEnabled();
- method public abstract boolean isWarnEnabled();
- method public abstract void trace(java.lang.Object);
- method public abstract void trace(java.lang.Object, java.lang.Throwable);
- method public abstract void warn(java.lang.Object);
- method public abstract void warn(java.lang.Object, java.lang.Throwable);
- }
-
-}
-
-package org.apache.http {
-
- public deprecated class ConnectionClosedException extends java.io.IOException {
- ctor public ConnectionClosedException(java.lang.String);
- }
-
- public abstract deprecated interface ConnectionReuseStrategy {
- method public abstract boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface FormattedHeader implements org.apache.http.Header {
- method public abstract org.apache.http.util.CharArrayBuffer getBuffer();
- method public abstract int getValuePos();
- }
-
- public abstract deprecated interface Header {
- method public abstract org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getValue();
- }
-
- public abstract deprecated interface HeaderElement {
- method public abstract java.lang.String getName();
- method public abstract org.apache.http.NameValuePair getParameter(int);
- method public abstract org.apache.http.NameValuePair getParameterByName(java.lang.String);
- method public abstract int getParameterCount();
- method public abstract org.apache.http.NameValuePair[] getParameters();
- method public abstract java.lang.String getValue();
- }
-
- public abstract deprecated interface HeaderElementIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract org.apache.http.HeaderElement nextElement();
- }
-
- public abstract deprecated interface HeaderIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract org.apache.http.Header nextHeader();
- }
-
- public abstract deprecated interface HttpClientConnection implements org.apache.http.HttpConnection {
- method public abstract void flush() throws java.io.IOException;
- method public abstract boolean isResponseAvailable(int) throws java.io.IOException;
- method public abstract void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpConnection {
- method public abstract void close() throws java.io.IOException;
- method public abstract org.apache.http.HttpConnectionMetrics getMetrics();
- method public abstract int getSocketTimeout();
- method public abstract boolean isOpen();
- method public abstract boolean isStale();
- method public abstract void setSocketTimeout(int);
- method public abstract void shutdown() throws java.io.IOException;
- }
-
- public abstract deprecated interface HttpConnectionMetrics {
- method public abstract java.lang.Object getMetric(java.lang.String);
- method public abstract long getReceivedBytesCount();
- method public abstract long getRequestCount();
- method public abstract long getResponseCount();
- method public abstract long getSentBytesCount();
- method public abstract void reset();
- }
-
- public abstract deprecated interface HttpEntity {
- method public abstract void consumeContent() throws java.io.IOException;
- method public abstract java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
- method public abstract org.apache.http.Header getContentEncoding();
- method public abstract long getContentLength();
- method public abstract org.apache.http.Header getContentType();
- method public abstract boolean isChunked();
- method public abstract boolean isRepeatable();
- method public abstract boolean isStreaming();
- method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public abstract deprecated interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest {
- method public abstract boolean expectContinue();
- method public abstract org.apache.http.HttpEntity getEntity();
- method public abstract void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class HttpException extends java.lang.Exception {
- ctor public HttpException();
- ctor public HttpException(java.lang.String);
- ctor public HttpException(java.lang.String, java.lang.Throwable);
- }
-
- public final deprecated class HttpHost implements java.lang.Cloneable {
- ctor public HttpHost(java.lang.String, int, java.lang.String);
- ctor public HttpHost(java.lang.String, int);
- ctor public HttpHost(java.lang.String);
- ctor public HttpHost(org.apache.http.HttpHost);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getHostName();
- method public int getPort();
- method public java.lang.String getSchemeName();
- method public java.lang.String toHostString();
- method public java.lang.String toURI();
- field public static final java.lang.String DEFAULT_SCHEME_NAME = "http";
- field protected final java.lang.String hostname;
- field protected final java.lang.String lcHostname;
- field protected final int port;
- field protected final java.lang.String schemeName;
- }
-
- public abstract deprecated interface HttpInetConnection implements org.apache.http.HttpConnection {
- method public abstract java.net.InetAddress getLocalAddress();
- method public abstract int getLocalPort();
- method public abstract java.net.InetAddress getRemoteAddress();
- method public abstract int getRemotePort();
- }
-
- public abstract deprecated interface HttpMessage {
- method public abstract void addHeader(org.apache.http.Header);
- method public abstract void addHeader(java.lang.String, java.lang.String);
- method public abstract boolean containsHeader(java.lang.String);
- method public abstract org.apache.http.Header[] getAllHeaders();
- method public abstract org.apache.http.Header getFirstHeader(java.lang.String);
- method public abstract org.apache.http.Header[] getHeaders(java.lang.String);
- method public abstract org.apache.http.Header getLastHeader(java.lang.String);
- method public abstract org.apache.http.params.HttpParams getParams();
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract org.apache.http.HeaderIterator headerIterator();
- method public abstract org.apache.http.HeaderIterator headerIterator(java.lang.String);
- method public abstract void removeHeader(org.apache.http.Header);
- method public abstract void removeHeaders(java.lang.String);
- method public abstract void setHeader(org.apache.http.Header);
- method public abstract void setHeader(java.lang.String, java.lang.String);
- method public abstract void setHeaders(org.apache.http.Header[]);
- method public abstract void setParams(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated interface HttpRequest implements org.apache.http.HttpMessage {
- method public abstract org.apache.http.RequestLine getRequestLine();
- }
-
- public abstract deprecated interface HttpRequestFactory {
- method public abstract org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
- method public abstract org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
- }
-
- public abstract deprecated interface HttpRequestInterceptor {
- method public abstract void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpResponse implements org.apache.http.HttpMessage {
- method public abstract org.apache.http.HttpEntity getEntity();
- method public abstract java.util.Locale getLocale();
- method public abstract org.apache.http.StatusLine getStatusLine();
- method public abstract void setEntity(org.apache.http.HttpEntity);
- method public abstract void setLocale(java.util.Locale);
- method public abstract void setReasonPhrase(java.lang.String) throws java.lang.IllegalStateException;
- method public abstract void setStatusCode(int) throws java.lang.IllegalStateException;
- method public abstract void setStatusLine(org.apache.http.StatusLine);
- method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int);
- method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- }
-
- public abstract deprecated interface HttpResponseFactory {
- method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
- method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface HttpResponseInterceptor {
- method public abstract void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpServerConnection implements org.apache.http.HttpConnection {
- method public abstract void flush() throws java.io.IOException;
- method public abstract void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public abstract void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpStatus {
- field public static final int SC_ACCEPTED = 202; // 0xca
- field public static final int SC_BAD_GATEWAY = 502; // 0x1f6
- field public static final int SC_BAD_REQUEST = 400; // 0x190
- field public static final int SC_CONFLICT = 409; // 0x199
- field public static final int SC_CONTINUE = 100; // 0x64
- field public static final int SC_CREATED = 201; // 0xc9
- field public static final int SC_EXPECTATION_FAILED = 417; // 0x1a1
- field public static final int SC_FAILED_DEPENDENCY = 424; // 0x1a8
- field public static final int SC_FORBIDDEN = 403; // 0x193
- field public static final int SC_GATEWAY_TIMEOUT = 504; // 0x1f8
- field public static final int SC_GONE = 410; // 0x19a
- field public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505; // 0x1f9
- field public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419; // 0x1a3
- field public static final int SC_INSUFFICIENT_STORAGE = 507; // 0x1fb
- field public static final int SC_INTERNAL_SERVER_ERROR = 500; // 0x1f4
- field public static final int SC_LENGTH_REQUIRED = 411; // 0x19b
- field public static final int SC_LOCKED = 423; // 0x1a7
- field public static final int SC_METHOD_FAILURE = 420; // 0x1a4
- field public static final int SC_METHOD_NOT_ALLOWED = 405; // 0x195
- field public static final int SC_MOVED_PERMANENTLY = 301; // 0x12d
- field public static final int SC_MOVED_TEMPORARILY = 302; // 0x12e
- field public static final int SC_MULTIPLE_CHOICES = 300; // 0x12c
- field public static final int SC_MULTI_STATUS = 207; // 0xcf
- field public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203; // 0xcb
- field public static final int SC_NOT_ACCEPTABLE = 406; // 0x196
- field public static final int SC_NOT_FOUND = 404; // 0x194
- field public static final int SC_NOT_IMPLEMENTED = 501; // 0x1f5
- field public static final int SC_NOT_MODIFIED = 304; // 0x130
- field public static final int SC_NO_CONTENT = 204; // 0xcc
- field public static final int SC_OK = 200; // 0xc8
- field public static final int SC_PARTIAL_CONTENT = 206; // 0xce
- field public static final int SC_PAYMENT_REQUIRED = 402; // 0x192
- field public static final int SC_PRECONDITION_FAILED = 412; // 0x19c
- field public static final int SC_PROCESSING = 102; // 0x66
- field public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407; // 0x197
- field public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; // 0x1a0
- field public static final int SC_REQUEST_TIMEOUT = 408; // 0x198
- field public static final int SC_REQUEST_TOO_LONG = 413; // 0x19d
- field public static final int SC_REQUEST_URI_TOO_LONG = 414; // 0x19e
- field public static final int SC_RESET_CONTENT = 205; // 0xcd
- field public static final int SC_SEE_OTHER = 303; // 0x12f
- field public static final int SC_SERVICE_UNAVAILABLE = 503; // 0x1f7
- field public static final int SC_SWITCHING_PROTOCOLS = 101; // 0x65
- field public static final int SC_TEMPORARY_REDIRECT = 307; // 0x133
- field public static final int SC_UNAUTHORIZED = 401; // 0x191
- field public static final int SC_UNPROCESSABLE_ENTITY = 422; // 0x1a6
- field public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415; // 0x19f
- field public static final int SC_USE_PROXY = 305; // 0x131
- }
-
- public final deprecated class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable {
- ctor public HttpVersion(int, int);
- field public static final java.lang.String HTTP = "HTTP";
- field public static final org.apache.http.HttpVersion HTTP_0_9;
- field public static final org.apache.http.HttpVersion HTTP_1_0;
- field public static final org.apache.http.HttpVersion HTTP_1_1;
- }
-
- public deprecated class MalformedChunkCodingException extends java.io.IOException {
- ctor public MalformedChunkCodingException();
- ctor public MalformedChunkCodingException(java.lang.String);
- }
-
- public deprecated class MethodNotSupportedException extends org.apache.http.HttpException {
- ctor public MethodNotSupportedException(java.lang.String);
- ctor public MethodNotSupportedException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface NameValuePair {
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getValue();
- }
-
- public deprecated class NoHttpResponseException extends java.io.IOException {
- ctor public NoHttpResponseException(java.lang.String);
- }
-
- public deprecated class ParseException extends java.lang.RuntimeException {
- ctor public ParseException();
- ctor public ParseException(java.lang.String);
- }
-
- public deprecated class ProtocolException extends org.apache.http.HttpException {
- ctor public ProtocolException();
- ctor public ProtocolException(java.lang.String);
- ctor public ProtocolException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class ProtocolVersion implements java.lang.Cloneable java.io.Serializable {
- ctor public ProtocolVersion(java.lang.String, int, int);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public int compareToVersion(org.apache.http.ProtocolVersion);
- method public final boolean equals(java.lang.Object);
- method public org.apache.http.ProtocolVersion forVersion(int, int);
- method public final int getMajor();
- method public final int getMinor();
- method public final java.lang.String getProtocol();
- method public final boolean greaterEquals(org.apache.http.ProtocolVersion);
- method public final int hashCode();
- method public boolean isComparable(org.apache.http.ProtocolVersion);
- method public final boolean lessEquals(org.apache.http.ProtocolVersion);
- field protected final int major;
- field protected final int minor;
- field protected final java.lang.String protocol;
- }
-
- public abstract deprecated interface ReasonPhraseCatalog {
- method public abstract java.lang.String getReason(int, java.util.Locale);
- }
-
- public abstract deprecated interface RequestLine {
- method public abstract java.lang.String getMethod();
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract java.lang.String getUri();
- }
-
- public abstract deprecated interface StatusLine {
- method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
- method public abstract java.lang.String getReasonPhrase();
- method public abstract int getStatusCode();
- }
-
- public abstract deprecated interface TokenIterator implements java.util.Iterator {
- method public abstract boolean hasNext();
- method public abstract java.lang.String nextToken();
- }
-
- public deprecated class UnsupportedHttpVersionException extends org.apache.http.ProtocolException {
- ctor public UnsupportedHttpVersionException();
- ctor public UnsupportedHttpVersionException(java.lang.String);
- }
-
-}
-
-package org.apache.http.auth {
-
- public final deprecated class AUTH {
- field public static final java.lang.String PROXY_AUTH = "Proxy-Authenticate";
- field public static final java.lang.String PROXY_AUTH_RESP = "Proxy-Authorization";
- field public static final java.lang.String WWW_AUTH = "WWW-Authenticate";
- field public static final java.lang.String WWW_AUTH_RESP = "Authorization";
- }
-
- public abstract deprecated interface AuthScheme {
- method public abstract org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public abstract java.lang.String getParameter(java.lang.String);
- method public abstract java.lang.String getRealm();
- method public abstract java.lang.String getSchemeName();
- method public abstract boolean isComplete();
- method public abstract boolean isConnectionBased();
- method public abstract void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public abstract deprecated interface AuthSchemeFactory {
- method public abstract org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public final deprecated class AuthSchemeRegistry {
- ctor public AuthSchemeRegistry();
- method public synchronized org.apache.http.auth.AuthScheme getAuthScheme(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
- method public synchronized java.util.List<java.lang.String> getSchemeNames();
- method public synchronized void register(java.lang.String, org.apache.http.auth.AuthSchemeFactory);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.auth.AuthSchemeFactory>);
- method public synchronized void unregister(java.lang.String);
- }
-
- public deprecated class AuthScope {
- ctor public AuthScope(java.lang.String, int, java.lang.String, java.lang.String);
- ctor public AuthScope(java.lang.String, int, java.lang.String);
- ctor public AuthScope(java.lang.String, int);
- ctor public AuthScope(org.apache.http.auth.AuthScope);
- method public java.lang.String getHost();
- method public int getPort();
- method public java.lang.String getRealm();
- method public java.lang.String getScheme();
- method public int match(org.apache.http.auth.AuthScope);
- field public static final org.apache.http.auth.AuthScope ANY;
- field public static final java.lang.String ANY_HOST;
- field public static final int ANY_PORT = -1; // 0xffffffff
- field public static final java.lang.String ANY_REALM;
- field public static final java.lang.String ANY_SCHEME;
- }
-
- public deprecated class AuthState {
- ctor public AuthState();
- method public org.apache.http.auth.AuthScheme getAuthScheme();
- method public org.apache.http.auth.AuthScope getAuthScope();
- method public org.apache.http.auth.Credentials getCredentials();
- method public void invalidate();
- method public boolean isValid();
- method public void setAuthScheme(org.apache.http.auth.AuthScheme);
- method public void setAuthScope(org.apache.http.auth.AuthScope);
- method public void setCredentials(org.apache.http.auth.Credentials);
- }
-
- public deprecated class AuthenticationException extends org.apache.http.ProtocolException {
- ctor public AuthenticationException();
- ctor public AuthenticationException(java.lang.String);
- ctor public AuthenticationException(java.lang.String, java.lang.Throwable);
- }
-
- public final deprecated class BasicUserPrincipal implements java.security.Principal {
- ctor public BasicUserPrincipal(java.lang.String);
- method public java.lang.String getName();
- }
-
- public abstract deprecated interface Credentials {
- method public abstract java.lang.String getPassword();
- method public abstract java.security.Principal getUserPrincipal();
- }
-
- public deprecated class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException {
- ctor public InvalidCredentialsException();
- ctor public InvalidCredentialsException(java.lang.String);
- ctor public InvalidCredentialsException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class MalformedChallengeException extends org.apache.http.ProtocolException {
- ctor public MalformedChallengeException();
- ctor public MalformedChallengeException(java.lang.String);
- ctor public MalformedChallengeException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class NTCredentials implements org.apache.http.auth.Credentials {
- ctor public NTCredentials(java.lang.String);
- ctor public NTCredentials(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- method public java.lang.String getDomain();
- method public java.lang.String getPassword();
- method public java.lang.String getUserName();
- method public java.security.Principal getUserPrincipal();
- method public java.lang.String getWorkstation();
- }
-
- public deprecated class NTUserPrincipal implements java.security.Principal {
- ctor public NTUserPrincipal(java.lang.String, java.lang.String);
- method public java.lang.String getDomain();
- method public java.lang.String getName();
- method public java.lang.String getUsername();
- }
-
- public deprecated class UsernamePasswordCredentials implements org.apache.http.auth.Credentials {
- ctor public UsernamePasswordCredentials(java.lang.String);
- ctor public UsernamePasswordCredentials(java.lang.String, java.lang.String);
- method public java.lang.String getPassword();
- method public java.lang.String getUserName();
- method public java.security.Principal getUserPrincipal();
- }
-
-}
-
-package org.apache.http.auth.params {
-
- public abstract deprecated interface AuthPNames {
- field public static final java.lang.String CREDENTIAL_CHARSET = "http.auth.credential-charset";
- }
-
- public deprecated class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public AuthParamBean(org.apache.http.params.HttpParams);
- method public void setCredentialCharset(java.lang.String);
- }
-
- public final deprecated class AuthParams {
- method public static java.lang.String getCredentialCharset(org.apache.http.params.HttpParams);
- method public static void setCredentialCharset(org.apache.http.params.HttpParams, java.lang.String);
- }
-
-}
-
-package org.apache.http.client {
-
- public abstract deprecated interface AuthenticationHandler {
- method public abstract java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public abstract boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- method public abstract org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
- }
-
- public deprecated class CircularRedirectException extends org.apache.http.client.RedirectException {
- ctor public CircularRedirectException();
- ctor public CircularRedirectException(java.lang.String);
- ctor public CircularRedirectException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class ClientProtocolException extends java.io.IOException {
- ctor public ClientProtocolException();
- ctor public ClientProtocolException(java.lang.String);
- ctor public ClientProtocolException(java.lang.Throwable);
- ctor public ClientProtocolException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface CookieStore {
- method public abstract void addCookie(org.apache.http.cookie.Cookie);
- method public abstract void clear();
- method public abstract boolean clearExpired(java.util.Date);
- method public abstract java.util.List<org.apache.http.cookie.Cookie> getCookies();
- }
-
- public abstract deprecated interface CredentialsProvider {
- method public abstract void clear();
- method public abstract org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
- method public abstract void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
- }
-
- public abstract deprecated interface HttpClient {
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public abstract org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public abstract org.apache.http.params.HttpParams getParams();
- }
-
- public abstract deprecated interface HttpRequestRetryHandler {
- method public abstract boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class HttpResponseException extends org.apache.http.client.ClientProtocolException {
- ctor public HttpResponseException(int, java.lang.String);
- method public int getStatusCode();
- }
-
- public deprecated class NonRepeatableRequestException extends org.apache.http.ProtocolException {
- ctor public NonRepeatableRequestException();
- ctor public NonRepeatableRequestException(java.lang.String);
- }
-
- public deprecated class RedirectException extends org.apache.http.ProtocolException {
- ctor public RedirectException();
- ctor public RedirectException(java.lang.String);
- ctor public RedirectException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface RedirectHandler {
- method public abstract java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
- method public abstract boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public abstract deprecated interface RequestDirector {
- method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface ResponseHandler {
- method public abstract T handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- }
-
- public abstract deprecated interface UserTokenHandler {
- method public abstract java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
- }
-
-}
-
-package org.apache.http.client.entity {
-
- public deprecated class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity {
- ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String) throws java.io.UnsupportedEncodingException;
- ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>) throws java.io.UnsupportedEncodingException;
- }
-
-}
-
-package org.apache.http.client.methods {
-
- public abstract deprecated interface AbortableHttpRequest {
- method public abstract void abort();
- method public abstract void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
- method public abstract void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
- }
-
- public deprecated class HttpDelete extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpDelete();
- ctor public HttpDelete(java.net.URI);
- ctor public HttpDelete(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "DELETE";
- }
-
- public abstract deprecated class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public HttpEntityEnclosingRequestBase();
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class HttpGet extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpGet();
- ctor public HttpGet(java.net.URI);
- ctor public HttpGet(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "GET";
- }
-
- public deprecated class HttpHead extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpHead();
- ctor public HttpHead(java.net.URI);
- ctor public HttpHead(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "HEAD";
- }
-
- public deprecated class HttpOptions extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpOptions();
- ctor public HttpOptions(java.net.URI);
- ctor public HttpOptions(java.lang.String);
- method public java.util.Set<java.lang.String> getAllowedMethods(org.apache.http.HttpResponse);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "OPTIONS";
- }
-
- public deprecated class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
- ctor public HttpPost();
- ctor public HttpPost(java.net.URI);
- ctor public HttpPost(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "POST";
- }
-
- public deprecated class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
- ctor public HttpPut();
- ctor public HttpPut(java.net.URI);
- ctor public HttpPut(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "PUT";
- }
-
- public abstract deprecated class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest {
- ctor public HttpRequestBase();
- method public void abort();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public abstract java.lang.String getMethod();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- method public java.net.URI getURI();
- method public boolean isAborted();
- method public void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
- method public void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
- method public void setURI(java.net.URI);
- }
-
- public deprecated class HttpTrace extends org.apache.http.client.methods.HttpRequestBase {
- ctor public HttpTrace();
- ctor public HttpTrace(java.net.URI);
- ctor public HttpTrace(java.lang.String);
- method public java.lang.String getMethod();
- field public static final java.lang.String METHOD_NAME = "TRACE";
- }
-
- public abstract deprecated interface HttpUriRequest implements org.apache.http.HttpRequest {
- method public abstract void abort() throws java.lang.UnsupportedOperationException;
- method public abstract java.lang.String getMethod();
- method public abstract java.net.URI getURI();
- method public abstract boolean isAborted();
- }
-
-}
-
-package org.apache.http.client.params {
-
- public abstract deprecated interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames {
- }
-
- public final deprecated class AuthPolicy {
- field public static final java.lang.String BASIC = "Basic";
- field public static final java.lang.String DIGEST = "Digest";
- field public static final java.lang.String NTLM = "NTLM";
- }
-
- public abstract deprecated interface ClientPNames {
- field public static final java.lang.String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
- field public static final java.lang.String CONNECTION_MANAGER_FACTORY = "http.connection-manager.factory-object";
- field public static final java.lang.String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
- field public static final java.lang.String COOKIE_POLICY = "http.protocol.cookie-policy";
- field public static final java.lang.String DEFAULT_HEADERS = "http.default-headers";
- field public static final java.lang.String DEFAULT_HOST = "http.default-host";
- field public static final java.lang.String HANDLE_AUTHENTICATION = "http.protocol.handle-authentication";
- field public static final java.lang.String HANDLE_REDIRECTS = "http.protocol.handle-redirects";
- field public static final java.lang.String MAX_REDIRECTS = "http.protocol.max-redirects";
- field public static final java.lang.String REJECT_RELATIVE_REDIRECT = "http.protocol.reject-relative-redirect";
- field public static final java.lang.String VIRTUAL_HOST = "http.virtual-host";
- }
-
- public deprecated class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ClientParamBean(org.apache.http.params.HttpParams);
- method public void setAllowCircularRedirects(boolean);
- method public void setConnectionManagerFactory(org.apache.http.conn.ClientConnectionManagerFactory);
- method public void setConnectionManagerFactoryClassName(java.lang.String);
- method public void setCookiePolicy(java.lang.String);
- method public void setDefaultHeaders(java.util.Collection<org.apache.http.Header>);
- method public void setDefaultHost(org.apache.http.HttpHost);
- method public void setHandleAuthentication(boolean);
- method public void setHandleRedirects(boolean);
- method public void setMaxRedirects(int);
- method public void setRejectRelativeRedirect(boolean);
- method public void setVirtualHost(org.apache.http.HttpHost);
- }
-
- public final deprecated class CookiePolicy {
- field public static final java.lang.String BEST_MATCH = "best-match";
- field public static final java.lang.String BROWSER_COMPATIBILITY = "compatibility";
- field public static final java.lang.String NETSCAPE = "netscape";
- field public static final java.lang.String RFC_2109 = "rfc2109";
- field public static final java.lang.String RFC_2965 = "rfc2965";
- }
-
- public deprecated class HttpClientParams {
- method public static java.lang.String getCookiePolicy(org.apache.http.params.HttpParams);
- method public static boolean isAuthenticating(org.apache.http.params.HttpParams);
- method public static boolean isRedirecting(org.apache.http.params.HttpParams);
- method public static void setAuthenticating(org.apache.http.params.HttpParams, boolean);
- method public static void setCookiePolicy(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setRedirecting(org.apache.http.params.HttpParams, boolean);
- }
-
-}
-
-package org.apache.http.client.protocol {
-
- public abstract deprecated interface ClientContext {
- field public static final java.lang.String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
- field public static final java.lang.String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
- field public static final java.lang.String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
- field public static final java.lang.String COOKIE_ORIGIN = "http.cookie-origin";
- field public static final java.lang.String COOKIE_SPEC = "http.cookie-spec";
- field public static final java.lang.String COOKIE_STORE = "http.cookie-store";
- field public static final java.lang.String CREDS_PROVIDER = "http.auth.credentials-provider";
- field public static final java.lang.String PROXY_AUTH_STATE = "http.auth.proxy-scope";
- field public static final java.lang.String TARGET_AUTH_STATE = "http.auth.target-scope";
- field public static final java.lang.String USER_TOKEN = "http.user-token";
- }
-
- public deprecated class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext {
- ctor public ClientContextConfigurer(org.apache.http.protocol.HttpContext);
- method public void setAuthSchemePref(java.util.List<java.lang.String>);
- method public void setAuthSchemeRegistry(org.apache.http.auth.AuthSchemeRegistry);
- method public void setCookieSpecRegistry(org.apache.http.cookie.CookieSpecRegistry);
- method public void setCookieStore(org.apache.http.client.CookieStore);
- method public void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
- }
-
- public deprecated class RequestAddCookies implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestAddCookies();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestDefaultHeaders();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestProxyAuthentication();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestTargetAuthentication();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseProcessCookies();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
-}
-
-package org.apache.http.client.utils {
-
- public deprecated class CloneUtils {
- method public static java.lang.Object clone(java.lang.Object) throws java.lang.CloneNotSupportedException;
- }
-
- public deprecated class URIUtils {
- method public static java.net.URI createURI(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
- method public static java.net.URI resolve(java.net.URI, java.lang.String);
- method public static java.net.URI resolve(java.net.URI, java.net.URI);
- method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost, boolean) throws java.net.URISyntaxException;
- method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost) throws java.net.URISyntaxException;
- }
-
- public deprecated class URLEncodedUtils {
- ctor public URLEncodedUtils();
- method public static java.lang.String format(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String);
- method public static boolean isEncoded(org.apache.http.HttpEntity);
- method public static java.util.List<org.apache.http.NameValuePair> parse(java.net.URI, java.lang.String);
- method public static java.util.List<org.apache.http.NameValuePair> parse(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static void parse(java.util.List<org.apache.http.NameValuePair>, java.util.Scanner, java.lang.String);
- field public static final java.lang.String CONTENT_TYPE = "application/x-www-form-urlencoded";
- }
-
-}
-
package org.apache.http.conn {
- public deprecated class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher {
- ctor public BasicEofSensorWatcher(org.apache.http.conn.ManagedClientConnection, boolean);
- method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- field protected boolean attemptReuse;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- }
-
- public deprecated class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher {
- ctor public BasicManagedEntity(org.apache.http.HttpEntity, org.apache.http.conn.ManagedClientConnection, boolean);
- method public void abortConnection() throws java.io.IOException;
- method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public void releaseConnection() throws java.io.IOException;
- method protected void releaseManagedConnection() throws java.io.IOException;
- method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- field protected final boolean attemptReuse;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- }
-
- public abstract deprecated interface ClientConnectionManager {
- method public abstract void closeExpiredConnections();
- method public abstract void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method public abstract org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public abstract void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public abstract org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public abstract void shutdown();
- }
-
- public abstract deprecated interface ClientConnectionManagerFactory {
- method public abstract org.apache.http.conn.ClientConnectionManager newInstance(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- }
-
- public abstract deprecated interface ClientConnectionOperator {
- method public abstract org.apache.http.conn.OperatedClientConnection createConnection();
- method public abstract void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public abstract deprecated interface ClientConnectionRequest {
- method public abstract void abortRequest();
- method public abstract org.apache.http.conn.ManagedClientConnection getConnection(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- }
-
public deprecated class ConnectTimeoutException extends java.io.InterruptedIOException {
ctor public ConnectTimeoutException();
ctor public ConnectTimeoutException(java.lang.String);
}
- public abstract deprecated interface ConnectionKeepAliveStrategy {
- method public abstract long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException {
- ctor public ConnectionPoolTimeoutException();
- ctor public ConnectionPoolTimeoutException(java.lang.String);
- }
-
- public abstract deprecated interface ConnectionReleaseTrigger {
- method public abstract void abortConnection() throws java.io.IOException;
- method public abstract void releaseConnection() throws java.io.IOException;
- }
-
- public deprecated class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger {
- ctor public EofSensorInputStream(java.io.InputStream, org.apache.http.conn.EofSensorWatcher);
- method public void abortConnection() throws java.io.IOException;
- method protected void checkAbort() throws java.io.IOException;
- method protected void checkClose() throws java.io.IOException;
- method protected void checkEOF(int) throws java.io.IOException;
- method protected boolean isReadAllowed() throws java.io.IOException;
- method public int read() throws java.io.IOException;
- method public void releaseConnection() throws java.io.IOException;
- field protected java.io.InputStream wrappedStream;
- }
-
- public abstract deprecated interface EofSensorWatcher {
- method public abstract boolean eofDetected(java.io.InputStream) throws java.io.IOException;
- method public abstract boolean streamAbort(java.io.InputStream) throws java.io.IOException;
- method public abstract boolean streamClosed(java.io.InputStream) throws java.io.IOException;
- }
-
- public deprecated class HttpHostConnectException extends java.net.ConnectException {
- ctor public HttpHostConnectException(org.apache.http.HttpHost, java.net.ConnectException);
- method public org.apache.http.HttpHost getHost();
- }
-
- public abstract deprecated interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
- method public abstract org.apache.http.conn.routing.HttpRoute getRoute();
- method public abstract javax.net.ssl.SSLSession getSSLSession();
- method public abstract java.lang.Object getState();
- method public abstract boolean isMarkedReusable();
- method public abstract boolean isSecure();
- method public abstract void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void markReusable();
- method public abstract void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void setIdleDuration(long, java.util.concurrent.TimeUnit);
- method public abstract void setState(java.lang.Object);
- method public abstract void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void unmarkReusable();
- }
-
- public final deprecated class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
- method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.Socket createSocket();
- method public static org.apache.http.conn.MultihomePlainSocketFactory getSocketFactory();
- method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
- }
-
- public abstract deprecated interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
- method public abstract java.net.Socket getSocket();
- method public abstract org.apache.http.HttpHost getTargetHost();
- method public abstract boolean isSecure();
- method public abstract void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public abstract void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
- method public abstract void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.conn.params {
-
- public abstract deprecated interface ConnConnectionPNames {
- field public static final java.lang.String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage";
- }
-
- public deprecated class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnConnectionParamBean(org.apache.http.params.HttpParams);
- method public void setMaxStatusLineGarbage(int);
- }
-
- public abstract deprecated interface ConnManagerPNames {
- field public static final java.lang.String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route";
- field public static final java.lang.String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total";
- field public static final java.lang.String TIMEOUT = "http.conn-manager.timeout";
- }
-
- public deprecated class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnManagerParamBean(org.apache.http.params.HttpParams);
- method public void setConnectionsPerRoute(org.apache.http.conn.params.ConnPerRouteBean);
- method public void setMaxTotalConnections(int);
- method public void setTimeout(long);
- }
-
- public final deprecated class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames {
- ctor public ConnManagerParams();
- method public static org.apache.http.conn.params.ConnPerRoute getMaxConnectionsPerRoute(org.apache.http.params.HttpParams);
- method public static int getMaxTotalConnections(org.apache.http.params.HttpParams);
- method public static long getTimeout(org.apache.http.params.HttpParams);
- method public static void setMaxConnectionsPerRoute(org.apache.http.params.HttpParams, org.apache.http.conn.params.ConnPerRoute);
- method public static void setMaxTotalConnections(org.apache.http.params.HttpParams, int);
- method public static void setTimeout(org.apache.http.params.HttpParams, long);
- field public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; // 0x14
- }
-
- public abstract deprecated interface ConnPerRoute {
- method public abstract int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
- }
-
- public final deprecated class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute {
- ctor public ConnPerRouteBean(int);
- ctor public ConnPerRouteBean();
- method public int getDefaultMax();
- method public int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
- method public void setDefaultMaxPerRoute(int);
- method public void setMaxForRoute(org.apache.http.conn.routing.HttpRoute, int);
- method public void setMaxForRoutes(java.util.Map<org.apache.http.conn.routing.HttpRoute, java.lang.Integer>);
- field public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // 0x2
- }
-
- public abstract deprecated interface ConnRoutePNames {
- field public static final java.lang.String DEFAULT_PROXY = "http.route.default-proxy";
- field public static final java.lang.String FORCED_ROUTE = "http.route.forced-route";
- field public static final java.lang.String LOCAL_ADDRESS = "http.route.local-address";
- }
-
- public deprecated class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public ConnRouteParamBean(org.apache.http.params.HttpParams);
- method public void setDefaultProxy(org.apache.http.HttpHost);
- method public void setForcedRoute(org.apache.http.conn.routing.HttpRoute);
- method public void setLocalAddress(java.net.InetAddress);
- }
-
- public deprecated class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames {
- method public static org.apache.http.HttpHost getDefaultProxy(org.apache.http.params.HttpParams);
- method public static org.apache.http.conn.routing.HttpRoute getForcedRoute(org.apache.http.params.HttpParams);
- method public static java.net.InetAddress getLocalAddress(org.apache.http.params.HttpParams);
- method public static void setDefaultProxy(org.apache.http.params.HttpParams, org.apache.http.HttpHost);
- method public static void setForcedRoute(org.apache.http.params.HttpParams, org.apache.http.conn.routing.HttpRoute);
- method public static void setLocalAddress(org.apache.http.params.HttpParams, java.net.InetAddress);
- field public static final org.apache.http.HttpHost NO_HOST;
- field public static final org.apache.http.conn.routing.HttpRoute NO_ROUTE;
- }
-
-}
-
-package org.apache.http.conn.routing {
-
- public deprecated class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector {
- ctor public BasicRouteDirector();
- method protected int directStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- method protected int firstStep(org.apache.http.conn.routing.RouteInfo);
- method public int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- method protected int proxiedStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- }
-
- public final deprecated class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost[], boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, boolean);
- ctor public HttpRoute(org.apache.http.HttpHost);
- ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public final boolean equals(java.lang.Object);
- method public final int getHopCount();
- method public final org.apache.http.HttpHost getHopTarget(int);
- method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public final java.net.InetAddress getLocalAddress();
- method public final org.apache.http.HttpHost getProxyHost();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public final int hashCode();
- method public final boolean isLayered();
- method public final boolean isSecure();
- method public final boolean isTunnelled();
- method public final java.lang.String toString();
- }
-
- public abstract deprecated interface HttpRouteDirector {
- method public abstract int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
- field public static final int COMPLETE = 0; // 0x0
- field public static final int CONNECT_PROXY = 2; // 0x2
- field public static final int CONNECT_TARGET = 1; // 0x1
- field public static final int LAYER_PROTOCOL = 5; // 0x5
- field public static final int TUNNEL_PROXY = 4; // 0x4
- field public static final int TUNNEL_TARGET = 3; // 0x3
- field public static final int UNREACHABLE = -1; // 0xffffffff
- }
-
- public abstract deprecated interface HttpRoutePlanner {
- method public abstract org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- }
-
- public abstract deprecated interface RouteInfo {
- method public abstract int getHopCount();
- method public abstract org.apache.http.HttpHost getHopTarget(int);
- method public abstract org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public abstract java.net.InetAddress getLocalAddress();
- method public abstract org.apache.http.HttpHost getProxyHost();
- method public abstract org.apache.http.HttpHost getTargetHost();
- method public abstract org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public abstract boolean isLayered();
- method public abstract boolean isSecure();
- method public abstract boolean isTunnelled();
- }
-
- public static final class RouteInfo.LayerType extends java.lang.Enum {
- method public static org.apache.http.conn.routing.RouteInfo.LayerType valueOf(java.lang.String);
- method public static final org.apache.http.conn.routing.RouteInfo.LayerType[] values();
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType LAYERED;
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.LayerType PLAIN;
- }
-
- public static final class RouteInfo.TunnelType extends java.lang.Enum {
- method public static org.apache.http.conn.routing.RouteInfo.TunnelType valueOf(java.lang.String);
- method public static final org.apache.http.conn.routing.RouteInfo.TunnelType[] values();
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType PLAIN;
- enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType TUNNELLED;
- }
-
- public final deprecated class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
- ctor public RouteTracker(org.apache.http.HttpHost, java.net.InetAddress);
- ctor public RouteTracker(org.apache.http.conn.routing.HttpRoute);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public final void connectProxy(org.apache.http.HttpHost, boolean);
- method public final void connectTarget(boolean);
- method public final boolean equals(java.lang.Object);
- method public final int getHopCount();
- method public final org.apache.http.HttpHost getHopTarget(int);
- method public final org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
- method public final java.net.InetAddress getLocalAddress();
- method public final org.apache.http.HttpHost getProxyHost();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final org.apache.http.conn.routing.RouteInfo.TunnelType getTunnelType();
- method public final int hashCode();
- method public final boolean isConnected();
- method public final boolean isLayered();
- method public final boolean isSecure();
- method public final boolean isTunnelled();
- method public final void layerProtocol(boolean);
- method public final org.apache.http.conn.routing.HttpRoute toRoute();
- method public final java.lang.String toString();
- method public final void tunnelProxy(org.apache.http.HttpHost, boolean);
- method public final void tunnelTarget(boolean);
- }
-
}
package org.apache.http.conn.scheme {
@@ -58433,37 +57354,6 @@
method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException;
}
- public final deprecated class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
- ctor public PlainSocketFactory(org.apache.http.conn.scheme.HostNameResolver);
- ctor public PlainSocketFactory();
- method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.Socket createSocket();
- method public static org.apache.http.conn.scheme.PlainSocketFactory getSocketFactory();
- method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
- }
-
- public final deprecated class Scheme {
- ctor public Scheme(java.lang.String, org.apache.http.conn.scheme.SocketFactory, int);
- method public final boolean equals(java.lang.Object);
- method public final int getDefaultPort();
- method public final java.lang.String getName();
- method public final org.apache.http.conn.scheme.SocketFactory getSocketFactory();
- method public final boolean isLayered();
- method public final int resolvePort(int);
- method public final java.lang.String toString();
- }
-
- public final deprecated class SchemeRegistry {
- ctor public SchemeRegistry();
- method public final synchronized org.apache.http.conn.scheme.Scheme get(java.lang.String);
- method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(java.lang.String);
- method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(org.apache.http.HttpHost);
- method public final synchronized java.util.List<java.lang.String> getSchemeNames();
- method public final synchronized org.apache.http.conn.scheme.Scheme register(org.apache.http.conn.scheme.Scheme);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.conn.scheme.Scheme>);
- method public final synchronized org.apache.http.conn.scheme.Scheme unregister(java.lang.String);
- }
-
public abstract deprecated interface SocketFactory {
method public abstract java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws org.apache.http.conn.ConnectTimeoutException, java.io.IOException, java.net.UnknownHostException;
method public abstract java.net.Socket createSocket() throws java.io.IOException;
@@ -58533,1818 +57423,8 @@
}
-package org.apache.http.conn.util {
-
- public deprecated class InetAddressUtils {
- method public static boolean isIPv4Address(java.lang.String);
- method public static boolean isIPv6Address(java.lang.String);
- method public static boolean isIPv6HexCompressedAddress(java.lang.String);
- method public static boolean isIPv6StdAddress(java.lang.String);
- }
-
-}
-
-package org.apache.http.cookie {
-
- public abstract deprecated interface ClientCookie implements org.apache.http.cookie.Cookie {
- method public abstract boolean containsAttribute(java.lang.String);
- method public abstract java.lang.String getAttribute(java.lang.String);
- field public static final java.lang.String COMMENTURL_ATTR = "commenturl";
- field public static final java.lang.String COMMENT_ATTR = "comment";
- field public static final java.lang.String DISCARD_ATTR = "discard";
- field public static final java.lang.String DOMAIN_ATTR = "domain";
- field public static final java.lang.String EXPIRES_ATTR = "expires";
- field public static final java.lang.String MAX_AGE_ATTR = "max-age";
- field public static final java.lang.String PATH_ATTR = "path";
- field public static final java.lang.String PORT_ATTR = "port";
- field public static final java.lang.String SECURE_ATTR = "secure";
- field public static final java.lang.String VERSION_ATTR = "version";
- }
-
- public abstract deprecated interface Cookie {
- method public abstract java.lang.String getComment();
- method public abstract java.lang.String getCommentURL();
- method public abstract java.lang.String getDomain();
- method public abstract java.util.Date getExpiryDate();
- method public abstract java.lang.String getName();
- method public abstract java.lang.String getPath();
- method public abstract int[] getPorts();
- method public abstract java.lang.String getValue();
- method public abstract int getVersion();
- method public abstract boolean isExpired(java.util.Date);
- method public abstract boolean isPersistent();
- method public abstract boolean isSecure();
- }
-
- public abstract deprecated interface CookieAttributeHandler {
- method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public abstract void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class CookieIdentityComparator implements java.util.Comparator java.io.Serializable {
- ctor public CookieIdentityComparator();
- method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
- }
-
- public final deprecated class CookieOrigin {
- ctor public CookieOrigin(java.lang.String, int, java.lang.String, boolean);
- method public java.lang.String getHost();
- method public java.lang.String getPath();
- method public int getPort();
- method public boolean isSecure();
- }
-
- public deprecated class CookiePathComparator implements java.util.Comparator java.io.Serializable {
- ctor public CookiePathComparator();
- method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
- }
-
- public abstract deprecated interface CookieSpec {
- method public abstract java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public abstract int getVersion();
- method public abstract org.apache.http.Header getVersionHeader();
- method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public abstract java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public abstract deprecated interface CookieSpecFactory {
- method public abstract org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public final deprecated class CookieSpecRegistry {
- ctor public CookieSpecRegistry();
- method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
- method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String) throws java.lang.IllegalStateException;
- method public synchronized java.util.List<java.lang.String> getSpecNames();
- method public synchronized void register(java.lang.String, org.apache.http.cookie.CookieSpecFactory);
- method public synchronized void setItems(java.util.Map<java.lang.String, org.apache.http.cookie.CookieSpecFactory>);
- method public synchronized void unregister(java.lang.String);
- }
-
- public deprecated class MalformedCookieException extends org.apache.http.ProtocolException {
- ctor public MalformedCookieException();
- ctor public MalformedCookieException(java.lang.String);
- ctor public MalformedCookieException(java.lang.String, java.lang.Throwable);
- }
-
- public abstract deprecated interface SM {
- field public static final java.lang.String COOKIE = "Cookie";
- field public static final java.lang.String COOKIE2 = "Cookie2";
- field public static final java.lang.String SET_COOKIE = "Set-Cookie";
- field public static final java.lang.String SET_COOKIE2 = "Set-Cookie2";
- }
-
- public abstract deprecated interface SetCookie implements org.apache.http.cookie.Cookie {
- method public abstract void setComment(java.lang.String);
- method public abstract void setDomain(java.lang.String);
- method public abstract void setExpiryDate(java.util.Date);
- method public abstract void setPath(java.lang.String);
- method public abstract void setSecure(boolean);
- method public abstract void setValue(java.lang.String);
- method public abstract void setVersion(int);
- }
-
- public abstract deprecated interface SetCookie2 implements org.apache.http.cookie.SetCookie {
- method public abstract void setCommentURL(java.lang.String);
- method public abstract void setDiscard(boolean);
- method public abstract void setPorts(int[]);
- }
-
-}
-
-package org.apache.http.cookie.params {
-
- public abstract deprecated interface CookieSpecPNames {
- field public static final java.lang.String DATE_PATTERNS = "http.protocol.cookie-datepatterns";
- field public static final java.lang.String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
- }
-
- public deprecated class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public CookieSpecParamBean(org.apache.http.params.HttpParams);
- method public void setDatePatterns(java.util.Collection<java.lang.String>);
- method public void setSingleHeader(boolean);
- }
-
-}
-
-package org.apache.http.entity {
-
- public abstract deprecated class AbstractHttpEntity implements org.apache.http.HttpEntity {
- ctor protected AbstractHttpEntity();
- method public void consumeContent() throws java.io.IOException, java.lang.UnsupportedOperationException;
- method public org.apache.http.Header getContentEncoding();
- method public org.apache.http.Header getContentType();
- method public boolean isChunked();
- method public void setChunked(boolean);
- method public void setContentEncoding(org.apache.http.Header);
- method public void setContentEncoding(java.lang.String);
- method public void setContentType(org.apache.http.Header);
- method public void setContentType(java.lang.String);
- field protected boolean chunked;
- field protected org.apache.http.Header contentEncoding;
- field protected org.apache.http.Header contentType;
- }
-
- public deprecated class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public BasicHttpEntity();
- method public java.io.InputStream getContent() throws java.lang.IllegalStateException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void setContent(java.io.InputStream);
- method public void setContentLength(long);
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper {
- ctor public BufferedHttpEntity(org.apache.http.HttpEntity) throws java.io.IOException;
- }
-
- public deprecated class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public ByteArrayEntity(byte[]);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent();
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final byte[] content;
- }
-
- public abstract deprecated interface ContentLengthStrategy {
- method public abstract long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- field public static final int CHUNKED = -2; // 0xfffffffe
- field public static final int IDENTITY = -1; // 0xffffffff
- }
-
- public abstract deprecated interface ContentProducer {
- method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity {
- ctor public EntityTemplate(org.apache.http.entity.ContentProducer);
- method public java.io.InputStream getContent();
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public FileEntity(java.io.File, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final java.io.File file;
- }
-
- public deprecated class HttpEntityWrapper implements org.apache.http.HttpEntity {
- ctor public HttpEntityWrapper(org.apache.http.HttpEntity);
- method public void consumeContent() throws java.io.IOException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public org.apache.http.Header getContentEncoding();
- method public long getContentLength();
- method public org.apache.http.Header getContentType();
- method public boolean isChunked();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected org.apache.http.HttpEntity wrappedEntity;
- }
-
- public deprecated class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public InputStreamEntity(java.io.InputStream, long);
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity {
- ctor public SerializableEntity(java.io.Serializable, boolean) throws java.io.IOException;
- method public java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- }
-
- public deprecated class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
- ctor public StringEntity(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
- ctor public StringEntity(java.lang.String) throws java.io.UnsupportedEncodingException;
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.io.InputStream getContent() throws java.io.IOException;
- method public long getContentLength();
- method public boolean isRepeatable();
- method public boolean isStreaming();
- method public void writeTo(java.io.OutputStream) throws java.io.IOException;
- field protected final byte[] content;
- }
-
-}
-
-package org.apache.http.impl {
-
- public abstract deprecated class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection {
- ctor public AbstractHttpClientConnection();
- method protected abstract void assertOpen() throws java.lang.IllegalStateException;
- method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
- method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
- method protected org.apache.http.HttpResponseFactory createHttpResponseFactory();
- method protected org.apache.http.io.HttpMessageWriter createRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method protected org.apache.http.io.HttpMessageParser createResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected void doFlush() throws java.io.IOException;
- method public void flush() throws java.io.IOException;
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method public boolean isResponseAvailable(int) throws java.io.IOException;
- method public boolean isStale();
- method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection {
- ctor public AbstractHttpServerConnection();
- method protected abstract void assertOpen() throws java.lang.IllegalStateException;
- method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
- method protected org.apache.http.impl.entity.EntitySerializer createEntitySerializer();
- method protected org.apache.http.HttpRequestFactory createHttpRequestFactory();
- method protected org.apache.http.io.HttpMessageParser createRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.io.HttpMessageWriter createResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method protected void doFlush() throws java.io.IOException;
- method public void flush() throws java.io.IOException;
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method protected void init(org.apache.http.io.SessionInputBuffer, org.apache.http.io.SessionOutputBuffer, org.apache.http.params.HttpParams);
- method public boolean isStale();
- method public void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void sendResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
- ctor public DefaultConnectionReuseStrategy();
- method protected org.apache.http.TokenIterator createTokenIterator(org.apache.http.HeaderIterator);
- method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection {
- ctor public DefaultHttpClientConnection();
- method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory {
- ctor public DefaultHttpRequestFactory();
- method public org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
- method public org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
- }
-
- public deprecated class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory {
- ctor public DefaultHttpResponseFactory(org.apache.http.ReasonPhraseCatalog);
- ctor public DefaultHttpResponseFactory();
- method protected java.util.Locale determineLocale(org.apache.http.protocol.HttpContext);
- method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
- method public org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
- field protected final org.apache.http.ReasonPhraseCatalog reasonCatalog;
- }
-
- public deprecated class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection {
- ctor public DefaultHttpServerConnection();
- method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog {
- ctor protected EnglishReasonPhraseCatalog();
- method public java.lang.String getReason(int, java.util.Locale);
- field public static final org.apache.http.impl.EnglishReasonPhraseCatalog INSTANCE;
- }
-
- public deprecated class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics {
- ctor public HttpConnectionMetricsImpl(org.apache.http.io.HttpTransportMetrics, org.apache.http.io.HttpTransportMetrics);
- method public java.lang.Object getMetric(java.lang.String);
- method public long getReceivedBytesCount();
- method public long getRequestCount();
- method public long getResponseCount();
- method public long getSentBytesCount();
- method public void incrementRequestCount();
- method public void incrementResponseCount();
- method public void reset();
- method public void setMetric(java.lang.String, java.lang.Object);
- field public static final java.lang.String RECEIVED_BYTES_COUNT = "http.received-bytes-count";
- field public static final java.lang.String REQUEST_COUNT = "http.request-count";
- field public static final java.lang.String RESPONSE_COUNT = "http.response-count";
- field public static final java.lang.String SENT_BYTES_COUNT = "http.sent-bytes-count";
- }
-
- public deprecated class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
- ctor public NoConnectionReuseStrategy();
- method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection {
- ctor public SocketHttpClientConnection();
- method protected void assertNotOpen();
- method protected void assertOpen();
- method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void close() throws java.io.IOException;
- method protected org.apache.http.io.SessionInputBuffer createSessionInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected org.apache.http.io.SessionOutputBuffer createSessionOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method protected java.net.Socket getSocket();
- method public int getSocketTimeout();
- method public boolean isOpen();
- method public void setSocketTimeout(int);
- method public void shutdown() throws java.io.IOException;
- }
-
- public deprecated class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection {
- ctor public SocketHttpServerConnection();
- method protected void assertNotOpen();
- method protected void assertOpen();
- method protected void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void close() throws java.io.IOException;
- method protected org.apache.http.io.SessionInputBuffer createHttpDataReceiver(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected org.apache.http.io.SessionOutputBuffer createHttpDataTransmitter(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method protected java.net.Socket getSocket();
- method public int getSocketTimeout();
- method public boolean isOpen();
- method public void setSocketTimeout(int);
- method public void shutdown() throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.impl.auth {
-
- public abstract deprecated class AuthSchemeBase implements org.apache.http.auth.AuthScheme {
- ctor public AuthSchemeBase();
- method public boolean isProxy();
- method protected abstract void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- method public void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public deprecated class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme {
- ctor public BasicScheme();
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public static org.apache.http.Header authenticate(org.apache.http.auth.Credentials, java.lang.String, boolean);
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- }
-
- public deprecated class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
- ctor public BasicSchemeFactory();
- method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme {
- ctor public DigestScheme();
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public static java.lang.String createCnonce();
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- method public void overrideParamter(java.lang.String, java.lang.String);
- }
-
- public deprecated class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
- ctor public DigestSchemeFactory();
- method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated interface NTLMEngine {
- method public abstract java.lang.String generateType1Msg(java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
- method public abstract java.lang.String generateType3Msg(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
- }
-
- public deprecated class NTLMEngineException extends org.apache.http.auth.AuthenticationException {
- ctor public NTLMEngineException();
- ctor public NTLMEngineException(java.lang.String);
- ctor public NTLMEngineException(java.lang.String, java.lang.Throwable);
- }
-
- public deprecated class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase {
- ctor public NTLMScheme(org.apache.http.impl.auth.NTLMEngine);
- method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
- method public java.lang.String getParameter(java.lang.String);
- method public java.lang.String getRealm();
- method public java.lang.String getSchemeName();
- method public boolean isComplete();
- method public boolean isConnectionBased();
- method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public abstract deprecated class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase {
- ctor public RFC2617Scheme();
- method public java.lang.String getParameter(java.lang.String);
- method protected java.util.Map<java.lang.String, java.lang.String> getParameters();
- method public java.lang.String getRealm();
- method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
- }
-
- public deprecated class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException {
- ctor public UnsupportedDigestAlgorithmException();
- ctor public UnsupportedDigestAlgorithmException(java.lang.String);
- ctor public UnsupportedDigestAlgorithmException(java.lang.String, java.lang.Throwable);
- }
-
-}
-
-package org.apache.http.impl.client {
-
- public abstract deprecated class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler {
- ctor public AbstractAuthenticationHandler();
- method protected java.util.List<java.lang.String> getAuthPreferences();
- method protected java.util.Map<java.lang.String, org.apache.http.Header> parseChallenges(org.apache.http.Header[]) throws org.apache.http.auth.MalformedChallengeException;
- method public org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
- }
-
- public abstract deprecated class AbstractHttpClient implements org.apache.http.client.HttpClient {
- ctor protected AbstractHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
- method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public synchronized void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public synchronized void clearRequestInterceptors();
- method public synchronized void clearResponseInterceptors();
- method protected abstract org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
- method protected abstract org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
- method protected org.apache.http.client.RequestDirector createClientRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
- method protected abstract org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
- method protected abstract org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
- method protected abstract org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
- method protected abstract org.apache.http.client.CookieStore createCookieStore();
- method protected abstract org.apache.http.client.CredentialsProvider createCredentialsProvider();
- method protected abstract org.apache.http.protocol.HttpContext createHttpContext();
- method protected abstract org.apache.http.params.HttpParams createHttpParams();
- method protected abstract org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
- method protected abstract org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
- method protected abstract org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
- method protected abstract org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
- method protected abstract org.apache.http.client.RedirectHandler createRedirectHandler();
- method protected abstract org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
- method protected abstract org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
- method protected abstract org.apache.http.client.UserTokenHandler createUserTokenHandler();
- method protected org.apache.http.params.HttpParams determineParams(org.apache.http.HttpRequest);
- method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public T execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.client.ResponseHandler<? extends T>, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
- method public final synchronized org.apache.http.auth.AuthSchemeRegistry getAuthSchemes();
- method public final synchronized org.apache.http.conn.ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy();
- method public final synchronized org.apache.http.conn.ClientConnectionManager getConnectionManager();
- method public final synchronized org.apache.http.ConnectionReuseStrategy getConnectionReuseStrategy();
- method public final synchronized org.apache.http.cookie.CookieSpecRegistry getCookieSpecs();
- method public final synchronized org.apache.http.client.CookieStore getCookieStore();
- method public final synchronized org.apache.http.client.CredentialsProvider getCredentialsProvider();
- method protected final synchronized org.apache.http.protocol.BasicHttpProcessor getHttpProcessor();
- method public final synchronized org.apache.http.client.HttpRequestRetryHandler getHttpRequestRetryHandler();
- method public final synchronized org.apache.http.params.HttpParams getParams();
- method public final synchronized org.apache.http.client.AuthenticationHandler getProxyAuthenticationHandler();
- method public final synchronized org.apache.http.client.RedirectHandler getRedirectHandler();
- method public final synchronized org.apache.http.protocol.HttpRequestExecutor getRequestExecutor();
- method public synchronized org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public synchronized int getRequestInterceptorCount();
- method public synchronized org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public synchronized int getResponseInterceptorCount();
- method public final synchronized org.apache.http.conn.routing.HttpRoutePlanner getRoutePlanner();
- method public final synchronized org.apache.http.client.AuthenticationHandler getTargetAuthenticationHandler();
- method public final synchronized org.apache.http.client.UserTokenHandler getUserTokenHandler();
- method public void removeRequestInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpRequestInterceptor>);
- method public void removeResponseInterceptorByClass(java.lang.Class<? extends org.apache.http.HttpResponseInterceptor>);
- method public synchronized void setAuthSchemes(org.apache.http.auth.AuthSchemeRegistry);
- method public synchronized void setCookieSpecs(org.apache.http.cookie.CookieSpecRegistry);
- method public synchronized void setCookieStore(org.apache.http.client.CookieStore);
- method public synchronized void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
- method public synchronized void setHttpRequestRetryHandler(org.apache.http.client.HttpRequestRetryHandler);
- method public synchronized void setKeepAliveStrategy(org.apache.http.conn.ConnectionKeepAliveStrategy);
- method public synchronized void setParams(org.apache.http.params.HttpParams);
- method public synchronized void setProxyAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
- method public synchronized void setRedirectHandler(org.apache.http.client.RedirectHandler);
- method public synchronized void setReuseStrategy(org.apache.http.ConnectionReuseStrategy);
- method public synchronized void setRoutePlanner(org.apache.http.conn.routing.HttpRoutePlanner);
- method public synchronized void setTargetAuthenticationHandler(org.apache.http.client.AuthenticationHandler);
- method public synchronized void setUserTokenHandler(org.apache.http.client.UserTokenHandler);
- }
-
- public deprecated class BasicCookieStore implements org.apache.http.client.CookieStore {
- ctor public BasicCookieStore();
- method public synchronized void addCookie(org.apache.http.cookie.Cookie);
- method public synchronized void addCookies(org.apache.http.cookie.Cookie[]);
- method public synchronized void clear();
- method public synchronized boolean clearExpired(java.util.Date);
- method public synchronized java.util.List<org.apache.http.cookie.Cookie> getCookies();
- }
-
- public deprecated class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider {
- ctor public BasicCredentialsProvider();
- method public synchronized void clear();
- method public synchronized org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
- method public synchronized void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
- }
-
- public deprecated class BasicResponseHandler implements org.apache.http.client.ResponseHandler {
- ctor public BasicResponseHandler();
- method public java.lang.String handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.HttpResponseException, java.io.IOException;
- }
-
- public deprecated class ClientParamsStack extends org.apache.http.params.AbstractHttpParams {
- ctor public ClientParamsStack(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack);
- ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- method public org.apache.http.params.HttpParams copy();
- method public final org.apache.http.params.HttpParams getApplicationParams();
- method public final org.apache.http.params.HttpParams getClientParams();
- method public final org.apache.http.params.HttpParams getOverrideParams();
- method public java.lang.Object getParameter(java.lang.String);
- method public final org.apache.http.params.HttpParams getRequestParams();
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object) throws java.lang.UnsupportedOperationException;
- field protected final org.apache.http.params.HttpParams applicationParams;
- field protected final org.apache.http.params.HttpParams clientParams;
- field protected final org.apache.http.params.HttpParams overrideParams;
- field protected final org.apache.http.params.HttpParams requestParams;
- }
-
- public deprecated class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy {
- ctor public DefaultConnectionKeepAliveStrategy();
- method public long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient {
- ctor public DefaultHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
- ctor public DefaultHttpClient(org.apache.http.params.HttpParams);
- ctor public DefaultHttpClient();
- method protected org.apache.http.auth.AuthSchemeRegistry createAuthSchemeRegistry();
- method protected org.apache.http.conn.ClientConnectionManager createClientConnectionManager();
- method protected org.apache.http.conn.ConnectionKeepAliveStrategy createConnectionKeepAliveStrategy();
- method protected org.apache.http.ConnectionReuseStrategy createConnectionReuseStrategy();
- method protected org.apache.http.cookie.CookieSpecRegistry createCookieSpecRegistry();
- method protected org.apache.http.client.CookieStore createCookieStore();
- method protected org.apache.http.client.CredentialsProvider createCredentialsProvider();
- method protected org.apache.http.protocol.HttpContext createHttpContext();
- method protected org.apache.http.params.HttpParams createHttpParams();
- method protected org.apache.http.protocol.BasicHttpProcessor createHttpProcessor();
- method protected org.apache.http.client.HttpRequestRetryHandler createHttpRequestRetryHandler();
- method protected org.apache.http.conn.routing.HttpRoutePlanner createHttpRoutePlanner();
- method protected org.apache.http.client.AuthenticationHandler createProxyAuthenticationHandler();
- method protected org.apache.http.client.RedirectHandler createRedirectHandler();
- method protected org.apache.http.protocol.HttpRequestExecutor createRequestExecutor();
- method protected org.apache.http.client.AuthenticationHandler createTargetAuthenticationHandler();
- method protected org.apache.http.client.UserTokenHandler createUserTokenHandler();
- }
-
- public deprecated class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler {
- ctor public DefaultHttpRequestRetryHandler(int, boolean);
- ctor public DefaultHttpRequestRetryHandler();
- method public int getRetryCount();
- method public boolean isRequestSentRetryEnabled();
- method public boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
- ctor public DefaultProxyAuthenticationHandler();
- method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler {
- ctor public DefaultRedirectHandler();
- method public java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
- method public boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultRequestDirector implements org.apache.http.client.RequestDirector {
- ctor public DefaultRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpRequest createConnectRequest(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext);
- method protected boolean createTunnelToProxy(org.apache.http.conn.routing.HttpRoute, int, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected boolean createTunnelToTarget(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method protected void establishRoute(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.impl.client.RoutedRequest handleResponse(org.apache.http.impl.client.RoutedRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected void releaseConnection();
- method protected void rewriteRequestURI(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute) throws org.apache.http.ProtocolException;
- field protected final org.apache.http.conn.ClientConnectionManager connManager;
- field protected final org.apache.http.protocol.HttpProcessor httpProcessor;
- field protected final org.apache.http.conn.ConnectionKeepAliveStrategy keepAliveStrategy;
- field protected org.apache.http.conn.ManagedClientConnection managedConn;
- field protected final org.apache.http.params.HttpParams params;
- field protected final org.apache.http.client.RedirectHandler redirectHandler;
- field protected final org.apache.http.protocol.HttpRequestExecutor requestExec;
- field protected final org.apache.http.client.HttpRequestRetryHandler retryHandler;
- field protected final org.apache.http.ConnectionReuseStrategy reuseStrategy;
- field protected final org.apache.http.conn.routing.HttpRoutePlanner routePlanner;
- }
-
- public deprecated class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
- ctor public DefaultTargetAuthenticationHandler();
- method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
- method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler {
- ctor public DefaultUserTokenHandler();
- method public java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public EntityEnclosingRequestWrapper(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.ProtocolException;
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class RedirectLocations {
- ctor public RedirectLocations();
- method public void add(java.net.URI);
- method public boolean contains(java.net.URI);
- method public boolean remove(java.net.URI);
- }
-
- public deprecated class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest {
- ctor public RequestWrapper(org.apache.http.HttpRequest) throws org.apache.http.ProtocolException;
- method public void abort() throws java.lang.UnsupportedOperationException;
- method public int getExecCount();
- method public java.lang.String getMethod();
- method public org.apache.http.HttpRequest getOriginal();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- method public java.net.URI getURI();
- method public void incrementExecCount();
- method public boolean isAborted();
- method public boolean isRepeatable();
- method public void resetHeaders();
- method public void setMethod(java.lang.String);
- method public void setProtocolVersion(org.apache.http.ProtocolVersion);
- method public void setURI(java.net.URI);
- }
-
- public deprecated class RoutedRequest {
- ctor public RoutedRequest(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute);
- method public final org.apache.http.impl.client.RequestWrapper getRequest();
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- field protected final org.apache.http.impl.client.RequestWrapper request;
- field protected final org.apache.http.conn.routing.HttpRoute route;
- }
-
- public deprecated class TunnelRefusedException extends org.apache.http.HttpException {
- ctor public TunnelRefusedException(java.lang.String, org.apache.http.HttpResponse);
- method public org.apache.http.HttpResponse getResponse();
- }
-
-}
-
-package org.apache.http.impl.conn {
-
- public abstract deprecated class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection {
- ctor protected AbstractClientConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.conn.OperatedClientConnection);
- method public void abortConnection();
- method protected final void assertNotAborted() throws java.io.InterruptedIOException;
- method protected final void assertValid(org.apache.http.conn.OperatedClientConnection);
- method protected void detach();
- method public void flush() throws java.io.IOException;
- method public java.net.InetAddress getLocalAddress();
- method public int getLocalPort();
- method protected org.apache.http.conn.ClientConnectionManager getManager();
- method public org.apache.http.HttpConnectionMetrics getMetrics();
- method public java.net.InetAddress getRemoteAddress();
- method public int getRemotePort();
- method public javax.net.ssl.SSLSession getSSLSession();
- method public int getSocketTimeout();
- method protected org.apache.http.conn.OperatedClientConnection getWrappedConnection();
- method public boolean isMarkedReusable();
- method public boolean isOpen();
- method public boolean isResponseAvailable(int) throws java.io.IOException;
- method public boolean isSecure();
- method public boolean isStale();
- method public void markReusable();
- method public void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse receiveResponseHeader() throws org.apache.http.HttpException, java.io.IOException;
- method public void releaseConnection();
- method public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
- method public void setIdleDuration(long, java.util.concurrent.TimeUnit);
- method public void setSocketTimeout(int);
- method public void unmarkReusable();
- }
-
- public abstract deprecated class AbstractPoolEntry {
- ctor protected AbstractPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute);
- method public java.lang.Object getState();
- method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void setState(java.lang.Object);
- method protected void shutdownEntry();
- method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected final org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected final org.apache.http.conn.OperatedClientConnection connection;
- field protected volatile org.apache.http.conn.routing.HttpRoute route;
- field protected volatile java.lang.Object state;
- field protected volatile org.apache.http.conn.routing.RouteTracker tracker;
- }
-
- public abstract deprecated class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter {
- ctor protected AbstractPooledConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.impl.conn.AbstractPoolEntry);
- method protected final void assertAttached();
- method public void close() throws java.io.IOException;
- method public org.apache.http.conn.routing.HttpRoute getRoute();
- method public java.lang.Object getState();
- method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void open(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void setState(java.lang.Object);
- method public void shutdown() throws java.io.IOException;
- method public void tunnelProxy(org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void tunnelTarget(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected volatile org.apache.http.impl.conn.AbstractPoolEntry poolEntry;
- }
-
- public deprecated class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection {
- ctor public DefaultClientConnection();
- method public final java.net.Socket getSocket();
- method public final org.apache.http.HttpHost getTargetHost();
- method public final boolean isSecure();
- method public void openCompleted(boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void opening(java.net.Socket, org.apache.http.HttpHost) throws java.io.IOException;
- method public void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
- public deprecated class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator {
- ctor public DefaultClientConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.OperatedClientConnection createConnection();
- method public void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method protected void prepareSocket(java.net.Socket, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
- ctor public DefaultHttpRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public DefaultResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class IdleConnectionHandler {
- ctor public IdleConnectionHandler();
- method public void add(org.apache.http.HttpConnection, long, java.util.concurrent.TimeUnit);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long);
- method public boolean remove(org.apache.http.HttpConnection);
- method public void removeAll();
- }
-
- public deprecated class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
- ctor public LoggingSessionInputBuffer(org.apache.http.io.SessionInputBuffer, org.apache.http.impl.conn.Wire);
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method public boolean isDataAvailable(int) throws java.io.IOException;
- method public int read(byte[], int, int) throws java.io.IOException;
- method public int read() throws java.io.IOException;
- method public int read(byte[]) throws java.io.IOException;
- method public java.lang.String readLine() throws java.io.IOException;
- method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
- public deprecated class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
- ctor public LoggingSessionOutputBuffer(org.apache.http.io.SessionOutputBuffer, org.apache.http.impl.conn.Wire);
- method public void flush() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method public void write(byte[], int, int) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method public void write(byte[]) throws java.io.IOException;
- method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public void writeLine(java.lang.String) throws java.io.IOException;
- }
-
- public deprecated class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
- ctor public ProxySelectorRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry, java.net.ProxySelector);
- method protected java.net.Proxy chooseProxy(java.util.List<java.net.Proxy>, org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext);
- method protected org.apache.http.HttpHost determineProxy(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- method protected java.lang.String getHost(java.net.InetSocketAddress);
- method public java.net.ProxySelector getProxySelector();
- method public void setProxySelector(java.net.ProxySelector);
- field protected java.net.ProxySelector proxySelector;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager {
- ctor public SingleClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- method protected final void assertStillUp() throws java.lang.IllegalStateException;
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method public org.apache.http.conn.ManagedClientConnection getConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public final org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method protected void revokeConnection();
- method public void shutdown();
- field public static final java.lang.String MISUSE_MESSAGE = "Invalid use of SingleClientConnManager: connection still allocated.\nMake sure to release the connection before allocating another one.";
- field protected boolean alwaysShutDown;
- field protected org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected long connectionExpiresTime;
- field protected volatile boolean isShutDown;
- field protected long lastReleaseTime;
- field protected org.apache.http.impl.conn.SingleClientConnManager.ConnAdapter managedConn;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- field protected org.apache.http.impl.conn.SingleClientConnManager.PoolEntry uniquePoolEntry;
- }
-
- protected class SingleClientConnManager.ConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
- ctor protected SingleClientConnManager.ConnAdapter(org.apache.http.impl.conn.SingleClientConnManager.PoolEntry, org.apache.http.conn.routing.HttpRoute);
- }
-
- protected class SingleClientConnManager.PoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
- ctor protected SingleClientConnManager.PoolEntry();
- method protected void close() throws java.io.IOException;
- method protected void shutdown() throws java.io.IOException;
- }
-
- public deprecated class Wire {
- ctor public Wire(org.apache.commons.logging.Log);
- method public boolean enabled();
- method public void input(java.io.InputStream) throws java.io.IOException;
- method public void input(byte[], int, int) throws java.io.IOException;
- method public void input(byte[]) throws java.io.IOException;
- method public void input(int) throws java.io.IOException;
- method public void input(java.lang.String) throws java.io.IOException;
- method public void output(java.io.InputStream) throws java.io.IOException;
- method public void output(byte[], int, int) throws java.io.IOException;
- method public void output(byte[]) throws java.io.IOException;
- method public void output(int) throws java.io.IOException;
- method public void output(java.lang.String) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.impl.conn.tsccm {
-
- public abstract deprecated class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler {
- ctor protected AbstractConnPool();
- method protected void closeConnection(org.apache.http.conn.OperatedClientConnection);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method public abstract void deleteClosedConnections();
- method public void enableConnectionGC() throws java.lang.IllegalStateException;
- method public abstract void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
- method public final org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- method protected abstract void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
- method public void handleReference(java.lang.ref.Reference);
- method public abstract org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public void shutdown();
- field protected org.apache.http.impl.conn.IdleConnectionHandler idleConnHandler;
- field protected volatile boolean isShutDown;
- field protected java.util.Set<org.apache.http.impl.conn.tsccm.BasicPoolEntryRef> issuedConnections;
- field protected int numConnections;
- field protected final java.util.concurrent.locks.Lock poolLock;
- field protected java.lang.ref.ReferenceQueue<java.lang.Object> refQueue;
- }
-
- public deprecated class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
- ctor public BasicPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute, java.lang.ref.ReferenceQueue<java.lang.Object>);
- method protected final org.apache.http.conn.OperatedClientConnection getConnection();
- method protected final org.apache.http.conn.routing.HttpRoute getPlannedRoute();
- method protected final org.apache.http.impl.conn.tsccm.BasicPoolEntryRef getWeakRef();
- }
-
- public deprecated class BasicPoolEntryRef extends java.lang.ref.WeakReference {
- ctor public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry, java.lang.ref.ReferenceQueue<java.lang.Object>);
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- }
-
- public deprecated class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
- ctor protected BasicPooledConnAdapter(org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager, org.apache.http.impl.conn.AbstractPoolEntry);
- method protected org.apache.http.impl.conn.AbstractPoolEntry getPoolEntry();
- }
-
- public deprecated class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool {
- ctor public ConnPoolByRoute(org.apache.http.conn.ClientConnectionOperator, org.apache.http.params.HttpParams);
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry createEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, org.apache.http.conn.ClientConnectionOperator);
- method protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> createFreeConnQueue();
- method protected java.util.Map<org.apache.http.conn.routing.HttpRoute, org.apache.http.impl.conn.tsccm.RouteSpecificPool> createRouteToPoolMap();
- method protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> createWaitingThreadQueue();
- method public void deleteClosedConnections();
- method protected void deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method protected void deleteLeastUsedEntry();
- method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry, boolean, long, java.util.concurrent.TimeUnit);
- method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getEntryBlocking(org.apache.http.conn.routing.HttpRoute, java.lang.Object, long, java.util.concurrent.TimeUnit, org.apache.http.impl.conn.tsccm.WaitingThreadAborter) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry getFreeEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, java.lang.Object);
- method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool getRoutePool(org.apache.http.conn.routing.HttpRoute, boolean);
- method protected void handleLostEntry(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.RouteSpecificPool newRouteSpecificPool(org.apache.http.conn.routing.HttpRoute);
- method protected org.apache.http.impl.conn.tsccm.WaitingThread newWaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method protected void notifyWaitingThread(org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method public org.apache.http.impl.conn.tsccm.PoolEntryRequest requestPoolEntry(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- field protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> freeConnections;
- field protected final int maxTotalConnections;
- field protected final org.apache.http.conn.ClientConnectionOperator operator;
- field protected final java.util.Map<org.apache.http.conn.routing.HttpRoute, org.apache.http.impl.conn.tsccm.RouteSpecificPool> routeToPool;
- field protected java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads;
- }
-
- public abstract deprecated interface PoolEntryRequest {
- method public abstract void abortRequest();
- method public abstract org.apache.http.impl.conn.tsccm.BasicPoolEntry getPoolEntry(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
- }
-
- public abstract deprecated interface RefQueueHandler {
- method public abstract void handleReference(java.lang.ref.Reference<?>);
- }
-
- public deprecated class RefQueueWorker implements java.lang.Runnable {
- ctor public RefQueueWorker(java.lang.ref.ReferenceQueue<?>, org.apache.http.impl.conn.tsccm.RefQueueHandler);
- method public void run();
- method public void shutdown();
- field protected final org.apache.http.impl.conn.tsccm.RefQueueHandler refHandler;
- field protected final java.lang.ref.ReferenceQueue<?> refQueue;
- field protected volatile java.lang.Thread workerThread;
- }
-
- public deprecated class RouteSpecificPool {
- ctor public RouteSpecificPool(org.apache.http.conn.routing.HttpRoute, int);
- method public org.apache.http.impl.conn.tsccm.BasicPoolEntry allocEntry(java.lang.Object);
- method public void createdEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public boolean deleteEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public void dropEntry();
- method public void freeEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
- method public int getCapacity();
- method public final int getEntryCount();
- method public final int getMaxEntries();
- method public final org.apache.http.conn.routing.HttpRoute getRoute();
- method public boolean hasThread();
- method public boolean isUnused();
- method public org.apache.http.impl.conn.tsccm.WaitingThread nextThread();
- method public void queueThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- method public void removeThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- field protected final java.util.LinkedList<org.apache.http.impl.conn.tsccm.BasicPoolEntry> freeEntries;
- field protected final int maxEntries;
- field protected int numEntries;
- field protected final org.apache.http.conn.routing.HttpRoute route;
- field protected final java.util.Queue<org.apache.http.impl.conn.tsccm.WaitingThread> waitingThreads;
- }
-
- public deprecated class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager {
- ctor public ThreadSafeClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
- method public void closeExpiredConnections();
- method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
- method protected org.apache.http.conn.ClientConnectionOperator createConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
- method protected org.apache.http.impl.conn.tsccm.AbstractConnPool createConnectionPool(org.apache.http.params.HttpParams);
- method public int getConnectionsInPool(org.apache.http.conn.routing.HttpRoute);
- method public int getConnectionsInPool();
- method public org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
- method public void releaseConnection(org.apache.http.conn.ManagedClientConnection, long, java.util.concurrent.TimeUnit);
- method public org.apache.http.conn.ClientConnectionRequest requestConnection(org.apache.http.conn.routing.HttpRoute, java.lang.Object);
- method public void shutdown();
- field protected org.apache.http.conn.ClientConnectionOperator connOperator;
- field protected final org.apache.http.impl.conn.tsccm.AbstractConnPool connectionPool;
- field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
- }
-
- public deprecated class WaitingThread {
- ctor public WaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
- method public boolean await(java.util.Date) throws java.lang.InterruptedException;
- method public final java.util.concurrent.locks.Condition getCondition();
- method public final org.apache.http.impl.conn.tsccm.RouteSpecificPool getPool();
- method public final java.lang.Thread getThread();
- method public void interrupt();
- method public void wakeup();
- }
-
- public deprecated class WaitingThreadAborter {
- ctor public WaitingThreadAborter();
- method public void abort();
- method public void setWaitingThread(org.apache.http.impl.conn.tsccm.WaitingThread);
- }
-
-}
-
-package org.apache.http.impl.cookie {
-
- public abstract deprecated class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public AbstractCookieAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public abstract deprecated class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec {
- ctor public AbstractCookieSpec();
- method protected org.apache.http.cookie.CookieAttributeHandler findAttribHandler(java.lang.String);
- method protected org.apache.http.cookie.CookieAttributeHandler getAttribHandler(java.lang.String);
- method protected java.util.Collection<org.apache.http.cookie.CookieAttributeHandler> getAttribHandlers();
- method public void registerAttribHandler(java.lang.String, org.apache.http.cookie.CookieAttributeHandler);
- }
-
- public deprecated class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie {
- ctor public BasicClientCookie(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public boolean containsAttribute(java.lang.String);
- method public java.lang.String getAttribute(java.lang.String);
- method public java.lang.String getComment();
- method public java.lang.String getCommentURL();
- method public java.lang.String getDomain();
- method public java.util.Date getExpiryDate();
- method public java.lang.String getName();
- method public java.lang.String getPath();
- method public int[] getPorts();
- method public java.lang.String getValue();
- method public int getVersion();
- method public boolean isExpired(java.util.Date);
- method public boolean isPersistent();
- method public boolean isSecure();
- method public void setAttribute(java.lang.String, java.lang.String);
- method public void setComment(java.lang.String);
- method public void setDomain(java.lang.String);
- method public void setExpiryDate(java.util.Date);
- method public void setPath(java.lang.String);
- method public void setSecure(boolean);
- method public void setValue(java.lang.String);
- method public void setVersion(int);
- }
-
- public deprecated class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 {
- ctor public BasicClientCookie2(java.lang.String, java.lang.String);
- method public void setCommentURL(java.lang.String);
- method public void setDiscard(boolean);
- method public void setPorts(int[]);
- }
-
- public deprecated class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicCommentHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public BasicDomainHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicExpiresHandler(java.lang.String[]);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicMaxAgeHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public BasicPathHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public BasicSecureHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BestMatchSpec implements org.apache.http.cookie.CookieSpec {
- ctor public BestMatchSpec(java.lang.String[], boolean);
- ctor public BestMatchSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public BestMatchSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public BrowserCompatSpec(java.lang.String[]);
- ctor public BrowserCompatSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- field protected static final java.lang.String[] DATE_PATTERNS;
- }
-
- public deprecated class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public BrowserCompatSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public abstract deprecated class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec {
- ctor public CookieSpecBase();
- method protected static java.lang.String getDefaultDomain(org.apache.http.cookie.CookieOrigin);
- method protected static java.lang.String getDefaultPath(org.apache.http.cookie.CookieOrigin);
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method protected java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.HeaderElement[], org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class DateParseException extends java.lang.Exception {
- ctor public DateParseException();
- ctor public DateParseException(java.lang.String);
- }
-
- public final deprecated class DateUtils {
- method public static java.lang.String formatDate(java.util.Date);
- method public static java.lang.String formatDate(java.util.Date, java.lang.String);
- method public static java.util.Date parseDate(java.lang.String) throws org.apache.http.impl.cookie.DateParseException;
- method public static java.util.Date parseDate(java.lang.String, java.lang.String[]) throws org.apache.http.impl.cookie.DateParseException;
- method public static java.util.Date parseDate(java.lang.String, java.lang.String[], java.util.Date) throws org.apache.http.impl.cookie.DateParseException;
- field public static final java.util.TimeZone GMT;
- field public static final java.lang.String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
- field public static final java.lang.String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
- field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
- }
-
- public deprecated class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler {
- ctor public NetscapeDomainHandler();
- }
-
- public deprecated class NetscapeDraftHeaderParser {
- ctor public NetscapeDraftHeaderParser();
- method public org.apache.http.HeaderElement parseHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- field public static final org.apache.http.impl.cookie.NetscapeDraftHeaderParser DEFAULT;
- }
-
- public deprecated class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public NetscapeDraftSpec(java.lang.String[]);
- ctor public NetscapeDraftSpec();
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- field protected static final java.lang.String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
- }
-
- public deprecated class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public NetscapeDraftSpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2109DomainHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase {
- ctor public RFC2109Spec(java.lang.String[], boolean);
- ctor public RFC2109Spec();
- method protected void formatCookieAsVer(org.apache.http.util.CharArrayBuffer, org.apache.http.cookie.Cookie, int);
- method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
- method protected void formatParamAsVer(org.apache.http.util.CharArrayBuffer, java.lang.String, java.lang.String, int);
- method public int getVersion();
- method public org.apache.http.Header getVersionHeader();
- method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public RFC2109SpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
- ctor public RFC2109VersionHandler();
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965CommentUrlAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965DiscardAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965DomainAttributeHandler();
- method public boolean domainMatch(java.lang.String, java.lang.String);
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965PortAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
- public deprecated class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec {
- ctor public RFC2965Spec();
- ctor public RFC2965Spec(java.lang.String[], boolean);
- }
-
- public deprecated class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
- ctor public RFC2965SpecFactory();
- method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
- }
-
- public deprecated class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
- ctor public RFC2965VersionAttributeHandler();
- method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
- method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
- method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
- }
-
-}
-
-package org.apache.http.impl.entity {
-
- public deprecated class EntityDeserializer {
- ctor public EntityDeserializer(org.apache.http.entity.ContentLengthStrategy);
- method public org.apache.http.HttpEntity deserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.entity.BasicHttpEntity doDeserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class EntitySerializer {
- ctor public EntitySerializer(org.apache.http.entity.ContentLengthStrategy);
- method protected java.io.OutputStream doSerialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method public void serialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage, org.apache.http.HttpEntity) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
- ctor public LaxContentLengthStrategy();
- method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- }
-
- public deprecated class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
- ctor public StrictContentLengthStrategy();
- method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
- }
-
-}
-
-package org.apache.http.impl.io {
-
- public abstract deprecated class AbstractMessageParser implements org.apache.http.io.HttpMessageParser {
- ctor public AbstractMessageParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.params.HttpParams);
- method public org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
- method protected abstract org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- method public static org.apache.http.Header[] parseHeaders(org.apache.http.io.SessionInputBuffer, int, int, org.apache.http.message.LineParser) throws org.apache.http.HttpException, java.io.IOException;
- field protected final org.apache.http.message.LineParser lineParser;
- }
-
- public abstract deprecated class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter {
- ctor public AbstractMessageWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method public void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- method protected abstract void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- field protected final org.apache.http.util.CharArrayBuffer lineBuf;
- field protected final org.apache.http.message.LineFormatter lineFormatter;
- field protected final org.apache.http.io.SessionOutputBuffer sessionBuffer;
- }
-
- public abstract deprecated class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
- ctor public AbstractSessionInputBuffer();
- method protected int fillBuffer() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method protected boolean hasBufferedData();
- method protected void init(java.io.InputStream, int, org.apache.http.params.HttpParams);
- method public int read() throws java.io.IOException;
- method public int read(byte[], int, int) throws java.io.IOException;
- method public int read(byte[]) throws java.io.IOException;
- method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public java.lang.String readLine() throws java.io.IOException;
- }
-
- public abstract deprecated class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
- ctor public AbstractSessionOutputBuffer();
- method public void flush() throws java.io.IOException;
- method protected void flushBuffer() throws java.io.IOException;
- method public org.apache.http.io.HttpTransportMetrics getMetrics();
- method protected void init(java.io.OutputStream, int, org.apache.http.params.HttpParams);
- method public void write(byte[], int, int) throws java.io.IOException;
- method public void write(byte[]) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method public void writeLine(java.lang.String) throws java.io.IOException;
- method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
- public deprecated class ChunkedInputStream extends java.io.InputStream {
- ctor public ChunkedInputStream(org.apache.http.io.SessionInputBuffer);
- method public org.apache.http.Header[] getFooters();
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class ChunkedOutputStream extends java.io.OutputStream {
- ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer, int) throws java.io.IOException;
- ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer) throws java.io.IOException;
- method public void finish() throws java.io.IOException;
- method protected void flushCache() throws java.io.IOException;
- method protected void flushCacheWithAppend(byte[], int, int) throws java.io.IOException;
- method public void write(int) throws java.io.IOException;
- method protected void writeClosingChunk() throws java.io.IOException;
- }
-
- public deprecated class ContentLengthInputStream extends java.io.InputStream {
- ctor public ContentLengthInputStream(org.apache.http.io.SessionInputBuffer, long);
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class ContentLengthOutputStream extends java.io.OutputStream {
- ctor public ContentLengthOutputStream(org.apache.http.io.SessionOutputBuffer, long);
- method public void write(int) throws java.io.IOException;
- }
-
- public deprecated class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public HttpRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- }
-
- public deprecated class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter {
- ctor public HttpRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- }
-
- public deprecated class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
- ctor public HttpResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
- method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
- }
-
- public deprecated class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter {
- ctor public HttpResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
- method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
- }
-
- public deprecated class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics {
- ctor public HttpTransportMetricsImpl();
- method public long getBytesTransferred();
- method public void incrementBytesTransferred(long);
- method public void reset();
- method public void setBytesTransferred(long);
- }
-
- public deprecated class IdentityInputStream extends java.io.InputStream {
- ctor public IdentityInputStream(org.apache.http.io.SessionInputBuffer);
- method public int read() throws java.io.IOException;
- }
-
- public deprecated class IdentityOutputStream extends java.io.OutputStream {
- ctor public IdentityOutputStream(org.apache.http.io.SessionOutputBuffer);
- method public void write(int) throws java.io.IOException;
- }
-
- public deprecated class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer {
- ctor public SocketInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- method public boolean isDataAvailable(int) throws java.io.IOException;
- }
-
- public deprecated class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer {
- ctor public SocketOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.io {
-
- public abstract deprecated interface HttpMessageParser {
- method public abstract org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpMessageWriter {
- method public abstract void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpTransportMetrics {
- method public abstract long getBytesTransferred();
- method public abstract void reset();
- }
-
- public abstract deprecated interface SessionInputBuffer {
- method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
- method public abstract boolean isDataAvailable(int) throws java.io.IOException;
- method public abstract int read(byte[], int, int) throws java.io.IOException;
- method public abstract int read(byte[]) throws java.io.IOException;
- method public abstract int read() throws java.io.IOException;
- method public abstract int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- method public abstract java.lang.String readLine() throws java.io.IOException;
- }
-
- public abstract deprecated interface SessionOutputBuffer {
- method public abstract void flush() throws java.io.IOException;
- method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
- method public abstract void write(byte[], int, int) throws java.io.IOException;
- method public abstract void write(byte[]) throws java.io.IOException;
- method public abstract void write(int) throws java.io.IOException;
- method public abstract void writeLine(java.lang.String) throws java.io.IOException;
- method public abstract void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
- }
-
-}
-
-package org.apache.http.message {
-
- public abstract deprecated class AbstractHttpMessage implements org.apache.http.HttpMessage {
- ctor protected AbstractHttpMessage(org.apache.http.params.HttpParams);
- ctor protected AbstractHttpMessage();
- method public void addHeader(org.apache.http.Header);
- method public void addHeader(java.lang.String, java.lang.String);
- method public boolean containsHeader(java.lang.String);
- method public org.apache.http.Header[] getAllHeaders();
- method public org.apache.http.Header getFirstHeader(java.lang.String);
- method public org.apache.http.Header[] getHeaders(java.lang.String);
- method public org.apache.http.Header getLastHeader(java.lang.String);
- method public org.apache.http.params.HttpParams getParams();
- method public org.apache.http.HeaderIterator headerIterator();
- method public org.apache.http.HeaderIterator headerIterator(java.lang.String);
- method public void removeHeader(org.apache.http.Header);
- method public void removeHeaders(java.lang.String);
- method public void setHeader(org.apache.http.Header);
- method public void setHeader(java.lang.String, java.lang.String);
- method public void setHeaders(org.apache.http.Header[]);
- method public void setParams(org.apache.http.params.HttpParams);
- field protected org.apache.http.message.HeaderGroup headergroup;
- field protected org.apache.http.params.HttpParams params;
- }
-
- public deprecated class BasicHeader implements java.lang.Cloneable org.apache.http.Header {
- ctor public BasicHeader(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement {
- ctor public BasicHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
- ctor public BasicHeaderElement(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getName();
- method public org.apache.http.NameValuePair getParameter(int);
- method public org.apache.http.NameValuePair getParameterByName(java.lang.String);
- method public int getParameterCount();
- method public org.apache.http.NameValuePair[] getParameters();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator {
- ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator, org.apache.http.message.HeaderValueParser);
- ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.HeaderElement nextElement() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- }
-
- public deprecated class BasicHeaderIterator implements org.apache.http.HeaderIterator {
- ctor public BasicHeaderIterator(org.apache.http.Header[], java.lang.String);
- method protected boolean filterHeader(int);
- method protected int findNext(int);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- field protected final org.apache.http.Header[] allHeaders;
- field protected int currentIndex;
- field protected java.lang.String headerName;
- }
-
- public deprecated class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter {
- ctor public BasicHeaderValueFormatter();
- method protected void doFormatValue(org.apache.http.util.CharArrayBuffer, java.lang.String, boolean);
- method protected int estimateElementsLen(org.apache.http.HeaderElement[]);
- method protected int estimateHeaderElementLen(org.apache.http.HeaderElement);
- method protected int estimateNameValuePairLen(org.apache.http.NameValuePair);
- method protected int estimateParametersLen(org.apache.http.NameValuePair[]);
- method public static final java.lang.String formatElements(org.apache.http.HeaderElement[], boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
- method public static final java.lang.String formatHeaderElement(org.apache.http.HeaderElement, boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
- method public static final java.lang.String formatNameValuePair(org.apache.http.NameValuePair, boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
- method public static final java.lang.String formatParameters(org.apache.http.NameValuePair[], boolean, org.apache.http.message.HeaderValueFormatter);
- method public org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
- method protected boolean isSeparator(char);
- method protected boolean isUnsafe(char);
- field public static final org.apache.http.message.BasicHeaderValueFormatter DEFAULT;
- field public static final java.lang.String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
- field public static final java.lang.String UNSAFE_CHARS = "\"\\";
- }
-
- public deprecated class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser {
- ctor public BasicHeaderValueParser();
- method protected org.apache.http.HeaderElement createHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
- method protected org.apache.http.NameValuePair createNameValuePair(java.lang.String, java.lang.String);
- method public static final org.apache.http.HeaderElement[] parseElements(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.HeaderElement parseHeaderElement(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.NameValuePair parseNameValuePair(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor, char[]);
- method public static final org.apache.http.NameValuePair[] parseParameters(java.lang.String, org.apache.http.message.HeaderValueParser) throws org.apache.http.ParseException;
- method public org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- field public static final org.apache.http.message.BasicHeaderValueParser DEFAULT;
- }
-
- public deprecated class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest {
- ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String);
- ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- ctor public BasicHttpEntityEnclosingRequest(org.apache.http.RequestLine);
- method public boolean expectContinue();
- method public org.apache.http.HttpEntity getEntity();
- method public void setEntity(org.apache.http.HttpEntity);
- }
-
- public deprecated class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest {
- ctor public BasicHttpRequest(java.lang.String, java.lang.String);
- ctor public BasicHttpRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- ctor public BasicHttpRequest(org.apache.http.RequestLine);
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public org.apache.http.RequestLine getRequestLine();
- }
-
- public deprecated class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse {
- ctor public BasicHttpResponse(org.apache.http.StatusLine, org.apache.http.ReasonPhraseCatalog, java.util.Locale);
- ctor public BasicHttpResponse(org.apache.http.StatusLine);
- ctor public BasicHttpResponse(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public org.apache.http.HttpEntity getEntity();
- method public java.util.Locale getLocale();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method protected java.lang.String getReason(int);
- method public org.apache.http.StatusLine getStatusLine();
- method public void setEntity(org.apache.http.HttpEntity);
- method public void setLocale(java.util.Locale);
- method public void setReasonPhrase(java.lang.String);
- method public void setStatusCode(int);
- method public void setStatusLine(org.apache.http.StatusLine);
- method public void setStatusLine(org.apache.http.ProtocolVersion, int);
- method public void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- }
-
- public deprecated class BasicLineFormatter implements org.apache.http.message.LineFormatter {
- ctor public BasicLineFormatter();
- method public org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
- method protected void doFormatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method protected void doFormatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method protected void doFormatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- method protected int estimateProtocolVersionLen(org.apache.http.ProtocolVersion);
- method public static final java.lang.String formatHeader(org.apache.http.Header, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method public static final java.lang.String formatProtocolVersion(org.apache.http.ProtocolVersion, org.apache.http.message.LineFormatter);
- method public static final java.lang.String formatRequestLine(org.apache.http.RequestLine, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method public static final java.lang.String formatStatusLine(org.apache.http.StatusLine, org.apache.http.message.LineFormatter);
- method public org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- method protected org.apache.http.util.CharArrayBuffer initBuffer(org.apache.http.util.CharArrayBuffer);
- field public static final org.apache.http.message.BasicLineFormatter DEFAULT;
- }
-
- public deprecated class BasicLineParser implements org.apache.http.message.LineParser {
- ctor public BasicLineParser(org.apache.http.ProtocolVersion);
- ctor public BasicLineParser();
- method protected org.apache.http.ProtocolVersion createProtocolVersion(int, int);
- method protected org.apache.http.RequestLine createRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- method protected org.apache.http.StatusLine createStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public static final org.apache.http.Header parseHeader(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public static final org.apache.http.ProtocolVersion parseProtocolVersion(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public static final org.apache.http.RequestLine parseRequestLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public static final org.apache.http.StatusLine parseStatusLine(java.lang.String, org.apache.http.message.LineParser) throws org.apache.http.ParseException;
- method public org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method protected void skipWhitespace(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- field public static final org.apache.http.message.BasicLineParser DEFAULT;
- field protected final org.apache.http.ProtocolVersion protocol;
- }
-
- public deprecated class BasicListHeaderIterator implements org.apache.http.HeaderIterator {
- ctor public BasicListHeaderIterator(java.util.List, java.lang.String);
- method protected boolean filterHeader(int);
- method protected int findNext(int);
- method public boolean hasNext();
- method public final java.lang.Object next() throws java.util.NoSuchElementException;
- method public org.apache.http.Header nextHeader() throws java.util.NoSuchElementException;
- method public void remove() throws java.lang.UnsupportedOperationException;
- field protected final java.util.List allHeaders;
- field protected int currentIndex;
- field protected java.lang.String headerName;
- field protected int lastIndex;
- }
-
- public deprecated class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair {
- ctor public BasicNameValuePair(java.lang.String, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- }
-
- public deprecated class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine {
- ctor public BasicRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public java.lang.String getMethod();
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public java.lang.String getUri();
- }
-
- public deprecated class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine {
- ctor public BasicStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.ProtocolVersion getProtocolVersion();
- method public java.lang.String getReasonPhrase();
- method public int getStatusCode();
- }
-
- public deprecated class BasicTokenIterator implements org.apache.http.TokenIterator {
- ctor public BasicTokenIterator(org.apache.http.HeaderIterator);
- method protected java.lang.String createToken(java.lang.String, int, int);
- method protected int findNext(int) throws org.apache.http.ParseException;
- method protected int findTokenEnd(int);
- method protected int findTokenSeparator(int);
- method protected int findTokenStart(int);
- method public boolean hasNext();
- method protected boolean isHttpSeparator(char);
- method protected boolean isTokenChar(char);
- method protected boolean isTokenSeparator(char);
- method protected boolean isWhitespace(char);
- method public final java.lang.Object next() throws java.util.NoSuchElementException, org.apache.http.ParseException;
- method public java.lang.String nextToken() throws java.util.NoSuchElementException, org.apache.http.ParseException;
- method public final void remove() throws java.lang.UnsupportedOperationException;
- field public static final java.lang.String HTTP_SEPARATORS = " ,;=()<>@:\\\"/[]?{}\t";
- field protected java.lang.String currentHeader;
- field protected java.lang.String currentToken;
- field protected final org.apache.http.HeaderIterator headerIt;
- field protected int searchPos;
- }
-
- public deprecated class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader {
- ctor public BufferedHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.util.CharArrayBuffer getBuffer();
- method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
- method public java.lang.String getName();
- method public java.lang.String getValue();
- method public int getValuePos();
- }
-
- public deprecated class HeaderGroup implements java.lang.Cloneable {
- ctor public HeaderGroup();
- method public void addHeader(org.apache.http.Header);
- method public void clear();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public boolean containsHeader(java.lang.String);
- method public org.apache.http.message.HeaderGroup copy();
- method public org.apache.http.Header[] getAllHeaders();
- method public org.apache.http.Header getCondensedHeader(java.lang.String);
- method public org.apache.http.Header getFirstHeader(java.lang.String);
- method public org.apache.http.Header[] getHeaders(java.lang.String);
- method public org.apache.http.Header getLastHeader(java.lang.String);
- method public org.apache.http.HeaderIterator iterator();
- method public org.apache.http.HeaderIterator iterator(java.lang.String);
- method public void removeHeader(org.apache.http.Header);
- method public void setHeaders(org.apache.http.Header[]);
- method public void updateHeader(org.apache.http.Header);
- }
-
- public abstract deprecated interface HeaderValueFormatter {
- method public abstract org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
- method public abstract org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
- }
-
- public abstract deprecated interface HeaderValueParser {
- method public abstract org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- }
-
- public abstract deprecated interface LineFormatter {
- method public abstract org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
- method public abstract org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
- method public abstract org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
- method public abstract org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
- }
-
- public abstract deprecated interface LineParser {
- method public abstract boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
- method public abstract org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
- method public abstract org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.RequestLine parseRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- method public abstract org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
- }
-
- public deprecated class ParserCursor {
- ctor public ParserCursor(int, int);
- method public boolean atEnd();
- method public int getLowerBound();
- method public int getPos();
- method public int getUpperBound();
- method public void updatePos(int);
- }
-
-}
-
package org.apache.http.params {
- public abstract deprecated class AbstractHttpParams implements org.apache.http.params.HttpParams {
- ctor protected AbstractHttpParams();
- method public boolean getBooleanParameter(java.lang.String, boolean);
- method public double getDoubleParameter(java.lang.String, double);
- method public int getIntParameter(java.lang.String, int);
- method public long getLongParameter(java.lang.String, long);
- method public boolean isParameterFalse(java.lang.String);
- method public boolean isParameterTrue(java.lang.String);
- method public org.apache.http.params.HttpParams setBooleanParameter(java.lang.String, boolean);
- method public org.apache.http.params.HttpParams setDoubleParameter(java.lang.String, double);
- method public org.apache.http.params.HttpParams setIntParameter(java.lang.String, int);
- method public org.apache.http.params.HttpParams setLongParameter(java.lang.String, long);
- }
-
- public final deprecated class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable {
- ctor public BasicHttpParams();
- method public void clear();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.params.HttpParams copy();
- method protected void copyParams(org.apache.http.params.HttpParams);
- method public java.lang.Object getParameter(java.lang.String);
- method public boolean isParameterSet(java.lang.String);
- method public boolean isParameterSetLocally(java.lang.String);
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
- method public void setParameters(java.lang.String[], java.lang.Object);
- }
-
public abstract deprecated interface CoreConnectionPNames {
field public static final java.lang.String CONNECTION_TIMEOUT = "http.connection.timeout";
field public static final java.lang.String MAX_HEADER_COUNT = "http.connection.max-header-count";
@@ -60356,41 +57436,6 @@
field public static final java.lang.String TCP_NODELAY = "http.tcp.nodelay";
}
- public abstract deprecated interface CoreProtocolPNames {
- field public static final java.lang.String HTTP_CONTENT_CHARSET = "http.protocol.content-charset";
- field public static final java.lang.String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
- field public static final java.lang.String ORIGIN_SERVER = "http.origin-server";
- field public static final java.lang.String PROTOCOL_VERSION = "http.protocol.version";
- field public static final java.lang.String STRICT_TRANSFER_ENCODING = "http.protocol.strict-transfer-encoding";
- field public static final java.lang.String USER_AGENT = "http.useragent";
- field public static final java.lang.String USE_EXPECT_CONTINUE = "http.protocol.expect-continue";
- field public static final java.lang.String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
- }
-
- public final deprecated class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams {
- ctor public DefaultedHttpParams(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
- method public org.apache.http.params.HttpParams copy();
- method public org.apache.http.params.HttpParams getDefaults();
- method public java.lang.Object getParameter(java.lang.String);
- method public boolean removeParameter(java.lang.String);
- method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
- }
-
- public abstract deprecated class HttpAbstractParamBean {
- ctor public HttpAbstractParamBean(org.apache.http.params.HttpParams);
- field protected final org.apache.http.params.HttpParams params;
- }
-
- public deprecated class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public HttpConnectionParamBean(org.apache.http.params.HttpParams);
- method public void setConnectionTimeout(int);
- method public void setLinger(int);
- method public void setSoTimeout(int);
- method public void setSocketBufferSize(int);
- method public void setStaleCheckingEnabled(boolean);
- method public void setTcpNoDelay(boolean);
- }
-
public final deprecated class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames {
method public static int getConnectionTimeout(org.apache.http.params.HttpParams);
method public static int getLinger(org.apache.http.params.HttpParams);
@@ -60423,359 +57468,6 @@
method public abstract org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
}
- public deprecated class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean {
- ctor public HttpProtocolParamBean(org.apache.http.params.HttpParams);
- method public void setContentCharset(java.lang.String);
- method public void setHttpElementCharset(java.lang.String);
- method public void setUseExpectContinue(boolean);
- method public void setUserAgent(java.lang.String);
- method public void setVersion(org.apache.http.HttpVersion);
- }
-
- public final deprecated class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames {
- method public static java.lang.String getContentCharset(org.apache.http.params.HttpParams);
- method public static java.lang.String getHttpElementCharset(org.apache.http.params.HttpParams);
- method public static java.lang.String getUserAgent(org.apache.http.params.HttpParams);
- method public static org.apache.http.ProtocolVersion getVersion(org.apache.http.params.HttpParams);
- method public static void setContentCharset(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setHttpElementCharset(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setUseExpectContinue(org.apache.http.params.HttpParams, boolean);
- method public static void setUserAgent(org.apache.http.params.HttpParams, java.lang.String);
- method public static void setVersion(org.apache.http.params.HttpParams, org.apache.http.ProtocolVersion);
- method public static boolean useExpectContinue(org.apache.http.params.HttpParams);
- }
-
-}
-
-package org.apache.http.protocol {
-
- public deprecated class BasicHttpContext implements org.apache.http.protocol.HttpContext {
- ctor public BasicHttpContext();
- ctor public BasicHttpContext(org.apache.http.protocol.HttpContext);
- method public java.lang.Object getAttribute(java.lang.String);
- method public java.lang.Object removeAttribute(java.lang.String);
- method public void setAttribute(java.lang.String, java.lang.Object);
- }
-
- public final deprecated class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList {
- ctor public BasicHttpProcessor();
- method public final void addInterceptor(org.apache.http.HttpRequestInterceptor);
- method public final void addInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public final void addInterceptor(org.apache.http.HttpResponseInterceptor);
- method public final void addInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public void clearInterceptors();
- method public void clearRequestInterceptors();
- method public void clearResponseInterceptors();
- method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
- method public org.apache.http.protocol.BasicHttpProcessor copy();
- method protected void copyInterceptors(org.apache.http.protocol.BasicHttpProcessor);
- method public org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public int getRequestInterceptorCount();
- method public org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public int getResponseInterceptorCount();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void removeRequestInterceptorByClass(java.lang.Class);
- method public void removeResponseInterceptorByClass(java.lang.Class);
- method public void setInterceptors(java.util.List);
- field protected java.util.List requestInterceptors;
- field protected java.util.List responseInterceptors;
- }
-
- public final deprecated class DefaultedHttpContext implements org.apache.http.protocol.HttpContext {
- ctor public DefaultedHttpContext(org.apache.http.protocol.HttpContext, org.apache.http.protocol.HttpContext);
- method public java.lang.Object getAttribute(java.lang.String);
- method public org.apache.http.protocol.HttpContext getDefaults();
- method public java.lang.Object removeAttribute(java.lang.String);
- method public void setAttribute(java.lang.String, java.lang.Object);
- }
-
- public abstract deprecated interface ExecutionContext {
- field public static final java.lang.String HTTP_CONNECTION = "http.connection";
- field public static final java.lang.String HTTP_PROXY_HOST = "http.proxy_host";
- field public static final java.lang.String HTTP_REQUEST = "http.request";
- field public static final java.lang.String HTTP_REQ_SENT = "http.request_sent";
- field public static final java.lang.String HTTP_RESPONSE = "http.response";
- field public static final java.lang.String HTTP_TARGET_HOST = "http.target_host";
- }
-
- public final deprecated class HTTP {
- method public static boolean isWhitespace(char);
- field public static final java.lang.String ASCII = "ASCII";
- field public static final java.lang.String CHARSET_PARAM = "; charset=";
- field public static final java.lang.String CHUNK_CODING = "chunked";
- field public static final java.lang.String CONN_CLOSE = "Close";
- field public static final java.lang.String CONN_DIRECTIVE = "Connection";
- field public static final java.lang.String CONN_KEEP_ALIVE = "Keep-Alive";
- field public static final java.lang.String CONTENT_ENCODING = "Content-Encoding";
- field public static final java.lang.String CONTENT_LEN = "Content-Length";
- field public static final java.lang.String CONTENT_TYPE = "Content-Type";
- field public static final int CR = 13; // 0xd
- field public static final java.lang.String DATE_HEADER = "Date";
- field public static final java.lang.String DEFAULT_CONTENT_CHARSET = "ISO-8859-1";
- field public static final java.lang.String DEFAULT_CONTENT_TYPE = "application/octet-stream";
- field public static final java.lang.String DEFAULT_PROTOCOL_CHARSET = "US-ASCII";
- field public static final java.lang.String EXPECT_CONTINUE = "100-continue";
- field public static final java.lang.String EXPECT_DIRECTIVE = "Expect";
- field public static final int HT = 9; // 0x9
- field public static final java.lang.String IDENTITY_CODING = "identity";
- field public static final java.lang.String ISO_8859_1 = "ISO-8859-1";
- field public static final int LF = 10; // 0xa
- field public static final java.lang.String OCTET_STREAM_TYPE = "application/octet-stream";
- field public static final java.lang.String PLAIN_TEXT_TYPE = "text/plain";
- field public static final java.lang.String SERVER_HEADER = "Server";
- field public static final int SP = 32; // 0x20
- field public static final java.lang.String TARGET_HOST = "Host";
- field public static final java.lang.String TRANSFER_ENCODING = "Transfer-Encoding";
- field public static final java.lang.String USER_AGENT = "User-Agent";
- field public static final java.lang.String US_ASCII = "US-ASCII";
- field public static final java.lang.String UTF_16 = "UTF-16";
- field public static final java.lang.String UTF_8 = "UTF-8";
- }
-
- public abstract deprecated interface HttpContext {
- method public abstract java.lang.Object getAttribute(java.lang.String);
- method public abstract java.lang.Object removeAttribute(java.lang.String);
- method public abstract void setAttribute(java.lang.String, java.lang.Object);
- field public static final java.lang.String RESERVED_PREFIX = "http.";
- }
-
- public deprecated class HttpDateGenerator {
- ctor public HttpDateGenerator();
- method public synchronized java.lang.String getCurrentDate();
- field public static final java.util.TimeZone GMT;
- field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
- }
-
- public abstract deprecated interface HttpExpectationVerifier {
- method public abstract void verify(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
- }
-
- public abstract deprecated interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor {
- }
-
- public deprecated class HttpRequestExecutor {
- ctor public HttpRequestExecutor();
- method protected boolean canResponseHaveBody(org.apache.http.HttpRequest, org.apache.http.HttpResponse);
- method protected org.apache.http.HttpResponse doReceiveResponse(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method protected org.apache.http.HttpResponse doSendRequest(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.HttpResponse execute(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void postProcess(org.apache.http.HttpResponse, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void preProcess(org.apache.http.HttpRequest, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public abstract deprecated interface HttpRequestHandler {
- method public abstract void handle(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver {
- ctor public HttpRequestHandlerRegistry();
- method public org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
- method protected deprecated boolean matchUriRequestPattern(java.lang.String, java.lang.String);
- method public void register(java.lang.String, org.apache.http.protocol.HttpRequestHandler);
- method public void setHandlers(java.util.Map);
- method public void unregister(java.lang.String);
- }
-
- public abstract deprecated interface HttpRequestHandlerResolver {
- method public abstract org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
- }
-
- public abstract deprecated interface HttpRequestInterceptorList {
- method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
- method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
- method public abstract void clearRequestInterceptors();
- method public abstract org.apache.http.HttpRequestInterceptor getRequestInterceptor(int);
- method public abstract int getRequestInterceptorCount();
- method public abstract void removeRequestInterceptorByClass(java.lang.Class);
- method public abstract void setInterceptors(java.util.List);
- }
-
- public abstract deprecated interface HttpResponseInterceptorList {
- method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
- method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
- method public abstract void clearResponseInterceptors();
- method public abstract org.apache.http.HttpResponseInterceptor getResponseInterceptor(int);
- method public abstract int getResponseInterceptorCount();
- method public abstract void removeResponseInterceptorByClass(java.lang.Class);
- method public abstract void setInterceptors(java.util.List);
- }
-
- public deprecated class HttpService {
- ctor public HttpService(org.apache.http.protocol.HttpProcessor, org.apache.http.ConnectionReuseStrategy, org.apache.http.HttpResponseFactory);
- method protected void doService(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public org.apache.http.params.HttpParams getParams();
- method protected void handleException(org.apache.http.HttpException, org.apache.http.HttpResponse);
- method public void handleRequest(org.apache.http.HttpServerConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- method public void setConnReuseStrategy(org.apache.http.ConnectionReuseStrategy);
- method public void setExpectationVerifier(org.apache.http.protocol.HttpExpectationVerifier);
- method public void setHandlerResolver(org.apache.http.protocol.HttpRequestHandlerResolver);
- method public void setHttpProcessor(org.apache.http.protocol.HttpProcessor);
- method public void setParams(org.apache.http.params.HttpParams);
- method public void setResponseFactory(org.apache.http.HttpResponseFactory);
- }
-
- public deprecated class RequestConnControl implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestConnControl();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestContent implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestContent();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestDate implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestDate();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestExpectContinue();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestTargetHost implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestTargetHost();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class RequestUserAgent implements org.apache.http.HttpRequestInterceptor {
- ctor public RequestUserAgent();
- method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseConnControl implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseConnControl();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseContent implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseContent();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseDate implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseDate();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class ResponseServer implements org.apache.http.HttpResponseInterceptor {
- ctor public ResponseServer();
- method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
- }
-
- public deprecated class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext {
- ctor public SyncBasicHttpContext(org.apache.http.protocol.HttpContext);
- }
-
- public deprecated class UriPatternMatcher {
- ctor public UriPatternMatcher();
- method public java.lang.Object lookup(java.lang.String);
- method protected boolean matchUriRequestPattern(java.lang.String, java.lang.String);
- method public void register(java.lang.String, java.lang.Object);
- method public void setHandlers(java.util.Map);
- method public void unregister(java.lang.String);
- }
-
-}
-
-package org.apache.http.util {
-
- public final deprecated class ByteArrayBuffer {
- ctor public ByteArrayBuffer(int);
- method public void append(byte[], int, int);
- method public void append(int);
- method public void append(char[], int, int);
- method public void append(org.apache.http.util.CharArrayBuffer, int, int);
- method public byte[] buffer();
- method public int byteAt(int);
- method public int capacity();
- method public void clear();
- method public boolean isEmpty();
- method public boolean isFull();
- method public int length();
- method public void setLength(int);
- method public byte[] toByteArray();
- }
-
- public final deprecated class CharArrayBuffer {
- ctor public CharArrayBuffer(int);
- method public void append(char[], int, int);
- method public void append(java.lang.String);
- method public void append(org.apache.http.util.CharArrayBuffer, int, int);
- method public void append(org.apache.http.util.CharArrayBuffer);
- method public void append(char);
- method public void append(byte[], int, int);
- method public void append(org.apache.http.util.ByteArrayBuffer, int, int);
- method public void append(java.lang.Object);
- method public char[] buffer();
- method public int capacity();
- method public char charAt(int);
- method public void clear();
- method public void ensureCapacity(int);
- method public int indexOf(int, int, int);
- method public int indexOf(int);
- method public boolean isEmpty();
- method public boolean isFull();
- method public int length();
- method public void setLength(int);
- method public java.lang.String substring(int, int);
- method public java.lang.String substringTrimmed(int, int);
- method public char[] toCharArray();
- }
-
- public final deprecated class EncodingUtils {
- method public static byte[] getAsciiBytes(java.lang.String);
- method public static java.lang.String getAsciiString(byte[], int, int);
- method public static java.lang.String getAsciiString(byte[]);
- method public static byte[] getBytes(java.lang.String, java.lang.String);
- method public static java.lang.String getString(byte[], int, int, java.lang.String);
- method public static java.lang.String getString(byte[], java.lang.String);
- }
-
- public final deprecated class EntityUtils {
- method public static java.lang.String getContentCharSet(org.apache.http.HttpEntity) throws org.apache.http.ParseException;
- method public static byte[] toByteArray(org.apache.http.HttpEntity) throws java.io.IOException;
- method public static java.lang.String toString(org.apache.http.HttpEntity, java.lang.String) throws java.io.IOException, org.apache.http.ParseException;
- method public static java.lang.String toString(org.apache.http.HttpEntity) throws java.io.IOException, org.apache.http.ParseException;
- }
-
- public final deprecated class ExceptionUtils {
- method public static void initCause(java.lang.Throwable, java.lang.Throwable);
- }
-
- public final deprecated class LangUtils {
- method public static boolean equals(java.lang.Object, java.lang.Object);
- method public static boolean equals(java.lang.Object[], java.lang.Object[]);
- method public static int hashCode(int, int);
- method public static int hashCode(int, boolean);
- method public static int hashCode(int, java.lang.Object);
- field public static final int HASH_OFFSET = 37; // 0x25
- field public static final int HASH_SEED = 17; // 0x11
- }
-
- public deprecated class VersionInfo {
- ctor protected VersionInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- method protected static final org.apache.http.util.VersionInfo fromMap(java.lang.String, java.util.Map, java.lang.ClassLoader);
- method public final java.lang.String getClassloader();
- method public final java.lang.String getModule();
- method public final java.lang.String getPackage();
- method public final java.lang.String getRelease();
- method public final java.lang.String getTimestamp();
- method public static final org.apache.http.util.VersionInfo[] loadVersionInfo(java.lang.String[], java.lang.ClassLoader);
- method public static final org.apache.http.util.VersionInfo loadVersionInfo(java.lang.String, java.lang.ClassLoader);
- field public static final java.lang.String PROPERTY_MODULE = "info.module";
- field public static final java.lang.String PROPERTY_RELEASE = "info.release";
- field public static final java.lang.String PROPERTY_TIMESTAMP = "info.timestamp";
- field public static final java.lang.String UNAVAILABLE = "UNAVAILABLE";
- field public static final java.lang.String VERSION_PROPERTY_FILE = "version.properties";
- }
-
}
package org.json {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 8997671..a501fa7 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -138,6 +138,7 @@
" am task lock <TASK_ID>\n" +
" am task lock stop\n" +
" am task resizeable <TASK_ID> [true|false]\n" +
+ " am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am get-config\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
@@ -249,11 +250,11 @@
"am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>" +
".\n" +
"\n" +
- "am stack split: split <STACK_ID> into 2 stacks <v>ertically or <h>orizontally" +
- " starting the new stack with [INTENT] if specified. If [INTENT] isn't" +
- " specified and the current stack has more than one task, then the top task" +
- " of the current task will be moved to the new stack. Command will also force" +
- " all current tasks in both stacks to be resizeable." +
+ "am stack split: split <STACK_ID> into 2 stacks <v>ertically or <h>orizontally\n" +
+ " starting the new stack with [INTENT] if specified. If [INTENT] isn't\n" +
+ " specified and the current stack has more than one task, then the top task\n" +
+ " of the current task will be moved to the new stack. Command will also force\n" +
+ " all current tasks in both stacks to be resizeable.\n" +
"\n" +
"am stack list: list all of the activity stacks and their sizes.\n" +
"\n" +
@@ -265,6 +266,10 @@
"\n" +
"am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" +
"\n" +
+ "am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.\n" +
+ " Forces the task to be resizeable and creates a stack if no existing stack\n" +
+ " has the specified bounds.\n" +
+ "\n" +
"am get-config: retrieve the configuration and any recent configurations\n" +
" of the device\n" +
"\n" +
@@ -1742,33 +1747,14 @@
private void runStackResize() throws Exception {
String stackIdStr = nextArgRequired();
int stackId = Integer.valueOf(stackIdStr);
- String leftStr = nextArgRequired();
- int left = Integer.valueOf(leftStr);
- String topStr = nextArgRequired();
- int top = Integer.valueOf(topStr);
- String rightStr = nextArgRequired();
- int right = Integer.valueOf(rightStr);
- String bottomStr = nextArgRequired();
- int bottom = Integer.valueOf(bottomStr);
- if (left < 0) {
- System.err.println("Error: bad left arg: " + leftStr);
- return;
- }
- if (top < 0) {
- System.err.println("Error: bad top arg: " + topStr);
- return;
- }
- if (right <= 0) {
- System.err.println("Error: bad right arg: " + rightStr);
- return;
- }
- if (bottom <= 0) {
- System.err.println("Error: bad bottom arg: " + bottomStr);
+ final Rect bounds = getBounds();
+ if (bounds == null) {
+ System.err.println("Error: invalid input bounds");
return;
}
try {
- mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
+ mAm.resizeStack(stackId, bounds);
} catch (RemoteException e) {
}
}
@@ -1823,16 +1809,18 @@
showError("Error: Unable to create new stack...");
}
- final StackInfo newStackInfo = mAm.getStackInfo(container.getStackId());
+ final int newStackId = container.getStackId();
if (intent != null) {
container.startActivity(intent);
} else if (currentStackInfo.taskIds != null && currentStackInfo.taskIds.length > 1) {
// Move top task over to new stack
mAm.moveTaskToStack(currentStackInfo.taskIds[currentStackInfo.taskIds.length - 1],
- newStackInfo.stackId, true);
+ newStackId, true);
}
+ final StackInfo newStackInfo = mAm.getStackInfo(newStackId);
+
// Make all tasks in the stacks resizeable.
for (int taskId : currentStackInfo.taskIds) {
mAm.setTaskResizeable(taskId, true);
@@ -1855,6 +1843,8 @@
runTaskLock();
} else if (op.equals("resizeable")) {
runTaskResizeable();
+ } else if (op.equals("resize")) {
+ runTaskResize();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -1888,6 +1878,20 @@
}
}
+ private void runTaskResize() throws Exception {
+ final String taskIdStr = nextArgRequired();
+ final int taskId = Integer.valueOf(taskIdStr);
+ final Rect bounds = getBounds();
+ if (bounds == null) {
+ System.err.println("Error: invalid input bounds");
+ return;
+ }
+ try {
+ mAm.resizeTask(taskId, bounds);
+ } catch (RemoteException e) {
+ }
+ }
+
private List<Configuration> getRecentConfigurations(int days) {
IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
Context.USAGE_STATS_SERVICE));
@@ -1984,4 +1988,32 @@
}
return fd;
}
+
+ private Rect getBounds() {
+ String leftStr = nextArgRequired();
+ int left = Integer.valueOf(leftStr);
+ String topStr = nextArgRequired();
+ int top = Integer.valueOf(topStr);
+ String rightStr = nextArgRequired();
+ int right = Integer.valueOf(rightStr);
+ String bottomStr = nextArgRequired();
+ int bottom = Integer.valueOf(bottomStr);
+ if (left < 0) {
+ System.err.println("Error: bad left arg: " + leftStr);
+ return null;
+ }
+ if (top < 0) {
+ System.err.println("Error: bad top arg: " + topStr);
+ return null;
+ }
+ if (right <= 0) {
+ System.err.println("Error: bad right arg: " + rightStr);
+ return null;
+ }
+ if (bottom <= 0) {
+ System.err.println("Error: bad bottom arg: " + bottomStr);
+ return null;
+ }
+ return new Rect(left, top, right, bottom);
+ }
}
diff --git a/cmds/bootanimation/AudioPlayer.cpp b/cmds/bootanimation/AudioPlayer.cpp
index 81fe5f8..2932130 100644
--- a/cmds/bootanimation/AudioPlayer.cpp
+++ b/cmds/bootanimation/AudioPlayer.cpp
@@ -305,7 +305,7 @@
exit:
if (pcm)
pcm_close(pcm);
- mCurrentFile->release();
+ delete mCurrentFile;
mCurrentFile = NULL;
return false;
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 1d4de22..bb25ec6 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -179,7 +179,7 @@
// FileMap memory is never released until application exit.
// Release it now as the texture is already loaded and the memory used for
// the packed resource can be released.
- frame.map->release();
+ delete frame.map;
// ensure we can call getPixels(). No need to call unlock, since the
// bitmap will go out of scope when we return from this method.
@@ -446,7 +446,7 @@
}
outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength());
- entryMap->release();
+ delete entryMap;
return true;
}
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
index 7a501a4..16532b8 100644
--- a/cmds/idmap/create.cpp
+++ b/cmds/idmap/create.cpp
@@ -7,6 +7,7 @@
#include <utils/String8.h>
#include <fcntl.h>
+#include <sys/file.h>
#include <sys/stat.h>
using namespace android;
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index bbe6eef2..197e36b 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -147,20 +147,20 @@
char *buf = new char[uncompLen];
if (NULL == buf) {
ALOGW("%s: failed to allocate %zd byte\n", __FUNCTION__, uncompLen);
- dataMap->release();
+ delete dataMap;
return -1;
}
StreamingZipInflater inflater(dataMap, uncompLen);
if (inflater.read(buf, uncompLen) < 0) {
ALOGW("%s: failed to inflate %zd byte\n", __FUNCTION__, uncompLen);
delete[] buf;
- dataMap->release();
+ delete dataMap;
return -1;
}
int priority = parse_manifest(buf, uncompLen, target_package_name);
delete[] buf;
- dataMap->release();
+ delete dataMap;
return priority;
}
}
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
index 26a61ae..5e88bca 100644
--- a/core/java/android/alsa/AlsaCardsParser.java
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -117,6 +117,9 @@
cardRecord.parse(line, 0);
line = bufferedReader.readLine();
+ if (line == null) {
+ break;
+ }
if (DEBUG) {
Slog.i(TAG, " " + line);
}
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6ef3da8..d5ae6c6 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -15,6 +15,7 @@
*/
package android.animation;
+import android.annotation.AnimatorRes;
import android.content.Context;
import android.content.res.ConfigurationBoundResourceCache;
import android.content.res.ConstantState;
@@ -82,7 +83,7 @@
* @return The animator object reference by the specified id
* @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
*/
- public static Animator loadAnimator(Context context, int id)
+ public static Animator loadAnimator(Context context, @AnimatorRes int id)
throws NotFoundException {
return loadAnimator(context.getResources(), context.getTheme(), id);
}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 014a7af..4cdd397 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -16,9 +16,12 @@
package android.app;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -256,7 +259,7 @@
*
* @see #setDisplayOptions(int, int)
*/
- public abstract void setCustomView(int resId);
+ public abstract void setCustomView(@LayoutRes int resId);
/**
* Set the icon to display in the 'home' section of the action bar.
@@ -271,7 +274,7 @@
* @see #setDisplayUseLogoEnabled(boolean)
* @see #setDisplayShowHomeEnabled(boolean)
*/
- public abstract void setIcon(int resId);
+ public abstract void setIcon(@DrawableRes int resId);
/**
* Set the icon to display in the 'home' section of the action bar.
@@ -301,7 +304,7 @@
* @see #setDisplayUseLogoEnabled(boolean)
* @see #setDisplayShowHomeEnabled(boolean)
*/
- public abstract void setLogo(int resId);
+ public abstract void setLogo(@DrawableRes int resId);
/**
* Set the logo to display in the 'home' section of the action bar.
@@ -397,7 +400,7 @@
* @see #setTitle(CharSequence)
* @see #setDisplayOptions(int, int)
*/
- public abstract void setTitle(int resId);
+ public abstract void setTitle(@StringRes int resId);
/**
* Set the action bar's subtitle. This will only be displayed if
@@ -420,7 +423,7 @@
* @see #setSubtitle(CharSequence)
* @see #setDisplayOptions(int, int)
*/
- public abstract void setSubtitle(int resId);
+ public abstract void setSubtitle(@StringRes int resId);
/**
* Set display options. This changes all display option bits at once. To change
@@ -892,7 +895,7 @@
* @see #setDisplayHomeAsUpEnabled(boolean)
* @see #setHomeActionContentDescription(int)
*/
- public void setHomeAsUpIndicator(int resId) { }
+ public void setHomeAsUpIndicator(@DrawableRes int resId) { }
/**
* Set an alternate description for the Home/Up action, when enabled.
@@ -931,7 +934,7 @@
* @see #setHomeAsUpIndicator(int)
* @see #setHomeAsUpIndicator(android.graphics.drawable.Drawable)
*/
- public void setHomeActionContentDescription(int resId) { }
+ public void setHomeActionContentDescription(@StringRes int resId) { }
/**
* Enable hiding the action bar on content scroll.
@@ -1154,7 +1157,7 @@
* @param resId Resource ID referring to the drawable to use as an icon
* @return The current instance for call chaining
*/
- public abstract Tab setIcon(int resId);
+ public abstract Tab setIcon(@DrawableRes int resId);
/**
* Set the text displayed on this tab. Text may be truncated if there is not
@@ -1172,7 +1175,7 @@
* @param resId A resource ID referring to the text that should be displayed
* @return The current instance for call chaining
*/
- public abstract Tab setText(int resId);
+ public abstract Tab setText(@StringRes int resId);
/**
* Set a custom view to be used for this tab. This overrides values set by
@@ -1190,7 +1193,7 @@
* @param layoutResId A layout resource to inflate and use as a custom tab view
* @return The current instance for call chaining
*/
- public abstract Tab setCustomView(int layoutResId);
+ public abstract Tab setCustomView(@LayoutRes int layoutResId);
/**
* Retrieve a previously set custom view for this tab.
@@ -1235,7 +1238,7 @@
* @see #setContentDescription(CharSequence)
* @see #getContentDescription()
*/
- public abstract Tab setContentDescription(int resId);
+ public abstract Tab setContentDescription(@StringRes int resId);
/**
* Set a description of this tab's content for use in accessibility support.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e95fbfc..f0d98f8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,7 +16,13 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.IntDef;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.os.PersistableBundle;
import android.transition.Scene;
import android.transition.TransitionManager;
@@ -743,6 +749,7 @@
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
final FragmentContainer mContainer = new FragmentContainer() {
@Override
+ @Nullable
public View findViewById(int id) {
return Activity.this.findViewById(id);
}
@@ -2068,7 +2075,8 @@
*
* @return The view if found or null otherwise.
*/
- public View findViewById(int id) {
+ @Nullable
+ public View findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
@@ -2141,7 +2149,7 @@
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
@@ -3609,7 +3617,7 @@
* Convenience for calling
* {@link android.view.Window#setFeatureDrawableResource}.
*/
- public final void setFeatureDrawableResource(int featureId, int resId) {
+ public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
getWindow().setFeatureDrawableResource(featureId, resId);
}
@@ -3664,7 +3672,7 @@
}
@Override
- protected void onApplyThemeResource(Resources.Theme theme, int resid,
+ protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid,
boolean first) {
if (mParent == null) {
super.onApplyThemeResource(theme, resid, first);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 47f57ea..bb307bb 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,7 +17,6 @@
package android.app;
import android.app.ActivityManager.StackInfo;
-import android.app.ProfilerInfo;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -51,6 +50,7 @@
import android.util.Log;
import android.util.Singleton;
import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.os.IResultReceiver;
import java.util.ArrayList;
import java.util.List;
@@ -2114,6 +2114,15 @@
return true;
}
+ case REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int requestType = data.readInt();
+ IResultReceiver receiver = IResultReceiver.Stub.asInterface(data.readStrongBinder());
+ requestAssistContextExtras(requestType, receiver);
+ reply.writeNoException();
+ return true;
+ }
+
case REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -2223,17 +2232,12 @@
return true;
}
- case GET_ACTIVITY_CONTAINER_TRANSACTION: {
+ case GET_ACTIVITY_DISPLAY_ID_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder activityToken = data.readStrongBinder();
- IActivityContainer activityContainer = getEnclosingActivityContainer(activityToken);
+ int displayId = getActivityDisplayId(activityToken);
reply.writeNoException();
- if (activityContainer != null) {
- reply.writeInt(1);
- reply.writeStrongBinder(activityContainer.asBinder());
- } else {
- reply.writeInt(0);
- }
+ reply.writeInt(displayId);
return true;
}
@@ -2309,6 +2313,15 @@
return true;
}
+ case RESIZE_TASK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int taskId = data.readInt();
+ Rect r = Rect.CREATOR.createFromParcel(data);
+ resizeTask(taskId, r);
+ reply.writeNoException();
+ return true;
+ }
+
case GET_TASK_DESCRIPTION_ICON_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String filename = data.readString();
@@ -5146,6 +5159,19 @@
return res;
}
+ public void requestAssistContextExtras(int requestType, IResultReceiver receiver)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(requestType);
+ data.writeStrongBinder(receiver.asBinder());
+ mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public void reportAssistContextExtras(IBinder token, Bundle extras)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -5275,6 +5301,7 @@
reply.recycle();
}
+ @Override
public IActivityContainer createStackOnDisplay(int displayId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -5294,26 +5321,22 @@
return res;
}
- public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
+ @Override
+ public int getActivityDisplayId(IBinder activityToken)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(activityToken);
- mRemote.transact(GET_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+ mRemote.transact(GET_ACTIVITY_DISPLAY_ID_TRANSACTION, data, reply, 0);
reply.readException();
- final int result = reply.readInt();
- final IActivityContainer res;
- if (result == 1) {
- res = IActivityContainer.Stub.asInterface(reply.readStrongBinder());
- } else {
- res = null;
- }
+ final int displayId = reply.readInt();
data.recycle();
reply.recycle();
- return res;
+ return displayId;
}
+ @Override
public IBinder getHomeActivityToken() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -5424,6 +5447,20 @@
}
@Override
+ public void resizeTask(int taskId, Rect r) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(taskId);
+ r.writeToParcel(data, 0);
+ mRemote.transact(RESIZE_TASK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 39ae65c..8909b28 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -140,6 +140,8 @@
public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
/** @hide */
public static final int ANIM_CUSTOM_IN_PLACE = 10;
+ /** @hide */
+ public static final int ANIM_CLIP_REVEAL = 11;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -291,6 +293,33 @@
}
/**
+ * Create an ActivityOptions specifying an animation where the new
+ * activity is revealed from a small originating area of the screen to
+ * its final full representation.
+ *
+ * @param source The View that the new activity is animating from. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param startX The x starting location of the new activity, relative to <var>source</var>.
+ * @param startY The y starting location of the activity, relative to <var>source</var>.
+ * @param width The initial width of the new activity.
+ * @param height The initial height of the new activity.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ */
+ public static ActivityOptions makeClipRevealAnimation(View source,
+ int startX, int startY, int width, int height) {
+ ActivityOptions opts = new ActivityOptions();
+ opts.mAnimationType = ANIM_CLIP_REVEAL;
+ int[] pts = new int[2];
+ source.getLocationOnScreen(pts);
+ opts.mStartX = pts[0] + startX;
+ opts.mStartY = pts[1] + startY;
+ opts.mWidth = width;
+ opts.mHeight = height;
+ return opts;
+ }
+
+ /**
* Create an ActivityOptions specifying an animation where a thumbnail
* is scaled from a given position to the new activity window that is
* being started.
@@ -582,6 +611,7 @@
break;
case ANIM_SCALE_UP:
+ case ANIM_CLIP_REVEAL:
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
@@ -809,6 +839,7 @@
b.putInt(KEY_ANIM_IN_PLACE_RES_ID, mCustomInPlaceResId);
break;
case ANIM_SCALE_UP:
+ case ANIM_CLIP_REVEAL:
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
b.putInt(KEY_ANIM_WIDTH, mWidth);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d781863..653b951 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1101,7 +1101,7 @@
@Override
public void dumpGfxInfo(FileDescriptor fd, String[] args) {
dumpGraphicsInfo(fd);
- WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
+ WindowManagerGlobal.getInstance().dumpGfxInfo(fd, args);
}
private void dumpDatabaseInfo(FileDescriptor fd, String[] args) {
@@ -2372,35 +2372,28 @@
return activity;
}
- private Context createBaseContextForActivity(ActivityClientRecord r,
- final Activity activity) {
- ContextImpl appContext =
- ContextImpl.createActivityContext(this, r.packageInfo, r.overrideConfig);
+ private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
+ int displayId = Display.DEFAULT_DISPLAY;
+ try {
+ displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
+ } catch (RemoteException e) {
+ }
+
+ ContextImpl appContext = ContextImpl.createActivityContext(
+ this, r.packageInfo, displayId, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- try {
- IActivityContainer container =
- ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token);
- final int displayId =
- container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId();
- if (displayId > Display.DEFAULT_DISPLAY) {
- Display display = dm.getRealDisplay(displayId, r.token);
- baseContext = appContext.createDisplayContext(display);
- }
- } catch (RemoteException e) {
- }
-
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
// its content on a secondary display if there is one.
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
- for (int displayId : dm.getDisplayIds()) {
- if (displayId != Display.DEFAULT_DISPLAY) {
- Display display = dm.getRealDisplay(displayId, r.token);
+ for (int id : dm.getDisplayIds()) {
+ if (id != Display.DEFAULT_DISPLAY) {
+ Display display = dm.getRealDisplay(id, r.overrideConfig);
baseContext = appContext.createDisplayContext(display);
break;
}
@@ -3870,6 +3863,7 @@
ActivityClientRecord existing = mActivities.get(token);
if (existing != null) {
target.startsNotResumed = existing.paused;
+ target.overrideConfig = existing.overrideConfig;
}
target.onlyLocalRequest = true;
}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 3c6458f..c8f58c6 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -18,6 +18,10 @@
import com.android.internal.app.AlertController;
+import android.annotation.ArrayRes;
+import android.annotation.AttrRes;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
@@ -117,7 +121,7 @@
* or one of the constants {@link #THEME_TRADITIONAL},
* {@link #THEME_HOLO_DARK}, or {@link #THEME_HOLO_LIGHT}.
*/
- protected AlertDialog(Context context, int theme) {
+ protected AlertDialog(Context context, @AttrRes int theme) {
this(context, theme, true);
}
@@ -327,7 +331,7 @@
* @param resId the resourceId of the drawable to use as the icon or 0
* if you don't want an icon.
*/
- public void setIcon(int resId) {
+ public void setIcon(@DrawableRes int resId) {
mAlert.setIcon(resId);
}
@@ -340,7 +344,7 @@
*
* @param attrId ID of a theme attribute that points to a drawable resource.
*/
- public void setIconAttribute(int attrId) {
+ public void setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
mContext.getTheme().resolveAttribute(attrId, out, true);
mAlert.setIcon(out.resourceId);
@@ -413,7 +417,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setTitle(int titleId) {
+ public Builder setTitle(@StringRes int titleId) {
P.mTitle = P.mContext.getText(titleId);
return this;
}
@@ -449,7 +453,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setMessage(int messageId) {
+ public Builder setMessage(@StringRes int messageId) {
P.mMessage = P.mContext.getText(messageId);
return this;
}
@@ -471,7 +475,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setIcon(int iconId) {
+ public Builder setIcon(@DrawableRes int iconId) {
P.mIconId = iconId;
return this;
}
@@ -495,7 +499,7 @@
*
* @param attrId ID of a theme attribute that points to a drawable resource.
*/
- public Builder setIconAttribute(int attrId) {
+ public Builder setIconAttribute(@AttrRes int attrId) {
TypedValue out = new TypedValue();
P.mContext.getTheme().resolveAttribute(attrId, out, true);
P.mIconId = out.resourceId;
@@ -509,7 +513,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setPositiveButton(int textId, final OnClickListener listener) {
+ public Builder setPositiveButton(@StringRes int textId, final OnClickListener listener) {
P.mPositiveButtonText = P.mContext.getText(textId);
P.mPositiveButtonListener = listener;
return this;
@@ -535,7 +539,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setNegativeButton(int textId, final OnClickListener listener) {
+ public Builder setNegativeButton(@StringRes int textId, final OnClickListener listener) {
P.mNegativeButtonText = P.mContext.getText(textId);
P.mNegativeButtonListener = listener;
return this;
@@ -561,7 +565,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setNeutralButton(int textId, final OnClickListener listener) {
+ public Builder setNeutralButton(@StringRes int textId, final OnClickListener listener) {
P.mNeutralButtonText = P.mContext.getText(textId);
P.mNeutralButtonListener = listener;
return this;
@@ -634,7 +638,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setItems(int itemsId, final OnClickListener listener) {
+ public Builder setItems(@ArrayRes int itemsId, final OnClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnClickListener = listener;
return this;
@@ -706,7 +710,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setMultiChoiceItems(int itemsId, boolean[] checkedItems,
+ public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems,
final OnMultiChoiceClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnCheckboxClickListener = listener;
@@ -785,7 +789,7 @@
*
* @return This Builder object to allow for chaining of calls to set methods
*/
- public Builder setSingleChoiceItems(int itemsId, int checkedItem,
+ public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem,
final OnClickListener listener) {
P.mItems = P.mContext.getResources().getTextArray(itemsId);
P.mOnClickListener = listener;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index d808c8b..f35e746 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -16,6 +16,9 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Intent;
@@ -730,7 +733,7 @@
}
}
- @Override public Drawable getDrawable(String packageName, int resid,
+ @Override public Drawable getDrawable(String packageName, @DrawableRes int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
Drawable dr = getCachedIcon(name);
@@ -1137,7 +1140,7 @@
}
@Override
- public CharSequence getText(String packageName, int resid,
+ public CharSequence getText(String packageName, @StringRes int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
CharSequence text = getCachedString(name);
@@ -1170,7 +1173,7 @@
}
@Override
- public XmlResourceParser getXml(String packageName, int resid,
+ public XmlResourceParser getXml(String packageName, @XmlRes int resid,
ApplicationInfo appInfo) {
if (appInfo == null) {
try {
diff --git a/core/java/android/app/AssistData.java b/core/java/android/app/AssistData.java
index 8d3d348..7b5eb6d 100644
--- a/core/java/android/app/AssistData.java
+++ b/core/java/android/app/AssistData.java
@@ -16,6 +16,7 @@
package android.app;
+import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
@@ -44,6 +45,8 @@
*/
public static final String ASSIST_KEY = "android:assist";
+ final ComponentName mActivityComponent;
+
final ArrayList<ViewNodeImpl> mRootViews = new ArrayList<>();
ViewAssistDataImpl mTmpViewAssistDataImpl = new ViewAssistDataImpl();
@@ -400,6 +403,7 @@
}
AssistData(Activity activity) {
+ mActivityComponent = activity.getComponentName();
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
activity.getActivityToken());
for (int i=0; i<views.size(); i++) {
@@ -414,6 +418,7 @@
}
AssistData(Parcel in) {
+ mActivityComponent = ComponentName.readFromParcel(in);
final int N = in.readInt();
for (int i=0; i<N; i++) {
mRootViews.add(new ViewNodeImpl(in));
@@ -421,7 +426,9 @@
//dump();
}
- void dump() {
+ /** @hide */
+ public void dump() {
+ Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
ViewNode node = new ViewNode();
final int N = getWindowCount();
for (int i=0; i<N; i++) {
@@ -445,7 +452,7 @@
}
String text = node.getText();
if (text != null) {
- Log.i(TAG, prefix + " Text (sel " + node.getTextSelectionStart() + "-"
+ Log.i(TAG, prefix + " Text (sel " + node.getTextSelectionStart() + "-"
+ node.getTextSelectionEnd() + "): " + text);
}
String hint = node.getHint();
@@ -476,6 +483,10 @@
return assistBundle.getParcelable(ASSIST_KEY);
}
+ public ComponentName getActivityComponent() {
+ return mActivityComponent;
+ }
+
/**
* Return the number of window contents that have been collected in this assist data.
*/
@@ -498,6 +509,7 @@
public void writeToParcel(Parcel out, int flags) {
int start = out.dataPosition();
+ ComponentName.writeToParcel(mActivityComponent, out);
final int N = mRootViews.size();
out.writeInt(N);
for (int i=0; i<N; i++) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6c78cab..503657b 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,12 +75,12 @@
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.MediaRouter;
+import android.media.midi.IMidiManager;
+import android.media.midi.MidiManager;
import android.media.projection.MediaProjectionManager;
import android.media.session.MediaSessionManager;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
-import android.midi.IMidiManager;
-import android.midi.MidiManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.EthernetManager;
@@ -2252,7 +2252,7 @@
ContextImpl context = new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
- context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
+ context.mResourcesManager.getDisplayMetricsLocked());
return context;
}
@@ -2263,9 +2263,11 @@
}
static ContextImpl createActivityContext(ActivityThread mainThread,
- LoadedApk packageInfo, Configuration overrideConfiguration) {
+ LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- return new ContextImpl(null, mainThread, packageInfo, null, null, false, null,
+ final Display display = ResourcesManager.getInstance().getAdjustedDisplay(
+ displayId, overrideConfiguration);
+ return new ContextImpl(null, mainThread, packageInfo, null, null, false, display,
overrideConfiguration);
}
@@ -2292,11 +2294,13 @@
if (container != null) {
compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
}
- if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {
- compatInfo = packageInfo.getCompatibilityInfo();
+ if (compatInfo == null) {
+ compatInfo = (displayId == Display.DEFAULT_DISPLAY)
+ ? packageInfo.getCompatibilityInfo()
+ : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
- mDisplayAdjustments.setActivityToken(activityToken);
+ mDisplayAdjustments.setConfiguration(overrideConfiguration);
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 70e6e5a..e465d57 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,8 +16,13 @@
package android.app;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import com.android.internal.app.WindowDecorActionBar;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
@@ -476,7 +481,8 @@
* @param id the identifier of the view to find
* @return The view with the given id or null.
*/
- public View findViewById(int id) {
+ @Nullable
+ public View findViewById(@IdRes int id) {
return mWindow.findViewById(id);
}
@@ -486,7 +492,7 @@
*
* @param layoutResID Resource ID to be inflated.
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
mWindow.setContentView(layoutResID);
}
@@ -540,7 +546,7 @@
*
* @param titleId the title's text resource identifier
*/
- public void setTitle(int titleId) {
+ public void setTitle(@StringRes int titleId) {
setTitle(mContext.getText(titleId));
}
@@ -1070,7 +1076,7 @@
* Convenience for calling
* {@link android.view.Window#setFeatureDrawableResource}.
*/
- public final void setFeatureDrawableResource(int featureId, int resId) {
+ public final void setFeatureDrawableResource(int featureId, @DrawableRes int resId) {
getWindow().setFeatureDrawableResource(featureId, resId);
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index ab28d95..bdcc312 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -18,6 +18,7 @@
import android.animation.Animator;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
@@ -795,7 +796,7 @@
*
* @param resId Resource id for the CharSequence text
*/
- public final CharSequence getText(int resId) {
+ public final CharSequence getText(@StringRes int resId) {
return getResources().getText(resId);
}
@@ -805,7 +806,7 @@
*
* @param resId Resource id for the string
*/
- public final String getString(int resId) {
+ public final String getString(@StringRes int resId) {
return getResources().getString(resId);
}
@@ -818,7 +819,7 @@
* @param formatArgs The format arguments that will be used for substitution.
*/
- public final String getString(int resId, Object... formatArgs) {
+ public final String getString(@StringRes int resId, Object... formatArgs) {
return getResources().getString(resId, formatArgs);
}
@@ -1243,7 +1244,7 @@
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
@@ -1309,7 +1310,7 @@
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
- public void onActivityCreated(Bundle savedInstanceState) {
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
@@ -2008,6 +2009,7 @@
mChildFragmentManager = new FragmentManagerImpl();
mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
@Override
+ @Nullable
public View findViewById(int id) {
if (mView == null) {
throw new IllegalStateException("Fragment does not have a view");
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index ccceef4..975b20d 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -19,7 +19,9 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
import android.content.Context;
+import android.annotation.IdRes;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
@@ -394,7 +396,8 @@
* Callbacks from FragmentManagerImpl to its container.
*/
interface FragmentContainer {
- public View findViewById(int id);
+ @Nullable
+ public View findViewById(@IdRes int id);
public boolean hasView();
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 467c99a..a7e9413 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -51,6 +51,7 @@
import android.os.StrictMode;
import android.service.voice.IVoiceInteractionSession;
import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.os.IResultReceiver;
import java.util.List;
@@ -419,6 +420,9 @@
public Bundle getAssistContextExtras(int requestType) throws RemoteException;
+ public void requestAssistContextExtras(int requestType, IResultReceiver receiver)
+ throws RemoteException;
+
public void reportAssistContextExtras(IBinder token, Bundle extras) throws RemoteException;
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle)
@@ -441,8 +445,7 @@
public void deleteActivityContainer(IActivityContainer container) throws RemoteException;
- public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
- throws RemoteException;
+ public int getActivityDisplayId(IBinder activityToken) throws RemoteException;
public IBinder getHomeActivityToken() throws RemoteException;
@@ -461,6 +464,7 @@
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
+ public void resizeTask(int taskId, Rect bounds) throws RemoteException;
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException;
public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
@@ -759,7 +763,7 @@
int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
- int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
+ int GET_ACTIVITY_DISPLAY_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185;
@@ -804,4 +808,6 @@
int CREATE_STACK_ON_DISPLAY = IBinder.FIRST_CALL_TRANSACTION+281;
int GET_FOCUSED_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+282;
int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
+ int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+284;
+ int RESIZE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+285;
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 88b9080..5d864df 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -75,6 +75,7 @@
ZenModeConfig getZenModeConfig();
boolean setZenModeConfig(in ZenModeConfig config);
+ oneway void setZenMode(int mode);
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
oneway void requestZenModeConditions(in IConditionListener callback, int relevance);
oneway void setZenModeCondition(in Condition condition);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 87e744c..9c00e1c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -165,6 +166,7 @@
* The resource id of a drawable to use as the icon in the status bar.
* This is required; notifications with an invalid icon resource will not be shown.
*/
+ @DrawableRes
public int icon;
/**
@@ -2128,7 +2130,7 @@
* A resource ID in the application's package of the drawable to use.
* @see Notification#icon
*/
- public Builder setSmallIcon(int icon) {
+ public Builder setSmallIcon(@DrawableRes int icon) {
mSmallIcon = icon;
return this;
}
@@ -2144,7 +2146,7 @@
* @see Notification#icon
* @see Notification#iconLevel
*/
- public Builder setSmallIcon(int icon, int level) {
+ public Builder setSmallIcon(@DrawableRes int icon, int level) {
mSmallIcon = icon;
mSmallIconLevel = level;
return this;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index cf54107..479327d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -27,6 +27,9 @@
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.UserHandle;
+import android.service.notification.Condition;
+import android.service.notification.IConditionListener;
+import android.service.notification.ZenModeConfig;
import android.util.Log;
/**
@@ -276,5 +279,53 @@
}
}
+ /**
+ * @hide
+ */
+ public void setZenMode(int mode) {
+ INotificationManager service = getService();
+ try {
+ service.setZenMode(mode);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void requestZenModeConditions(IConditionListener listener, int relevance) {
+ INotificationManager service = getService();
+ try {
+ service.requestZenModeConditions(listener, relevance);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setZenModeCondition(Condition exitCondition) {
+ INotificationManager service = getService();
+ try {
+ service.setZenModeCondition(exitCondition);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public Condition getZenModeCondition() {
+ INotificationManager service = getService();
+ try {
+ final ZenModeConfig config = service.getZenModeConfig();
+ if (config != null) {
+ return config.exitCondition;
+ }
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
private Context mContext;
}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index fac40b2..75ccb23 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -27,6 +27,7 @@
import android.hardware.display.DisplayManagerGlobal;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
+import android.util.Pair;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayAdjustments;
@@ -40,11 +41,10 @@
private static final boolean DEBUG = false;
private static ResourcesManager sResourcesManager;
- final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources
- = new ArrayMap<ResourcesKey, WeakReference<Resources> >();
-
- final ArrayMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
- = new ArrayMap<DisplayAdjustments, DisplayMetrics>();
+ private final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources =
+ new ArrayMap<>();
+ private final ArrayMap<Pair<Integer, Configuration>, WeakReference<Display>> mDisplays =
+ new ArrayMap<>();
CompatibilityInfo mResCompatibilityInfo;
@@ -63,46 +63,18 @@
return mResConfiguration;
}
- public void flushDisplayMetricsLocked() {
- mDefaultDisplayMetrics.clear();
+ DisplayMetrics getDisplayMetricsLocked() {
+ return getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
}
- public DisplayMetrics getDisplayMetricsLocked(int displayId) {
- return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
- }
-
- public DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
- if (dm != null) {
- return dm;
- }
- dm = new DisplayMetrics();
-
- DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
- if (displayManager == null) {
- // may be null early in system startup
- dm.setToDefaults();
- return dm;
- }
-
- if (isDefaultDisplay) {
- mDefaultDisplayMetrics.put(daj, dm);
- }
-
- Display d = displayManager.getCompatibleDisplay(displayId, daj);
- if (d != null) {
- d.getMetrics(dm);
+ DisplayMetrics getDisplayMetricsLocked(int displayId) {
+ DisplayMetrics dm = new DisplayMetrics();
+ final Display display = getAdjustedDisplay(displayId, Configuration.EMPTY);
+ if (display != null) {
+ display.getMetrics(dm);
} else {
- // Display no longer exists
- // FIXME: This would not be a problem if we kept the Display object around
- // instead of using the raw display id everywhere. The Display object caches
- // its information even after the display has been removed.
dm.setToDefaults();
}
- //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
- // + metrics.heightPixels + " den=" + metrics.density
- // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
return dm;
}
@@ -138,6 +110,38 @@
}
/**
+ * Returns an adjusted {@link Display} object based on the inputs or null if display isn't
+ * available.
+ *
+ * @param displayId display Id.
+ * @param overrideConfiguration override configurations.
+ */
+ public Display getAdjustedDisplay(final int displayId, Configuration overrideConfiguration) {
+ final Configuration configCopy = (overrideConfiguration != null)
+ ? new Configuration(overrideConfiguration) : new Configuration();
+ final Pair<Integer, Configuration> key = Pair.create(displayId, configCopy);
+ synchronized (this) {
+ WeakReference<Display> wd = mDisplays.get(key);
+ if (wd != null) {
+ final Display display = wd.get();
+ if (display != null) {
+ return display;
+ }
+ }
+ final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+ if (dm == null) {
+ // may be null early in system startup
+ return null;
+ }
+ final Display display = dm.getRealDisplay(displayId, key.second);
+ if (display != null) {
+ mDisplays.put(key, new WeakReference<>(display));
+ }
+ return display;
+ }
+ }
+
+ /**
* Creates the top level Resources for applications with the given compatibility info.
*
* @param resDir the resource directory.
@@ -148,7 +152,7 @@
* @param overrideConfiguration override configurations.
* @param compatInfo the compatibility info. Must not be null.
*/
- public Resources getTopLevelResources(String resDir, String[] splitResDirs,
+ Resources getTopLevelResources(String resDir, String[] splitResDirs,
String[] overlayDirs, String[] libDirs, int displayId,
Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
final float scale = compatInfo.applicationScale;
@@ -247,7 +251,7 @@
}
}
- public final boolean applyConfigurationToResourcesLocked(Configuration config,
+ final boolean applyConfigurationToResourcesLocked(Configuration config,
CompatibilityInfo compat) {
if (mResConfiguration == null) {
mResConfiguration = new Configuration();
@@ -258,8 +262,9 @@
return false;
}
int changes = mResConfiguration.updateFrom(config);
- flushDisplayMetricsLocked();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
+ // Things might have changed in display manager, so clear the cached displays.
+ mDisplays.clear();
+ DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked();
if (compat != null && (mResCompatibilityInfo == null ||
!mResCompatibilityInfo.equals(compat))) {
@@ -281,7 +286,7 @@
Configuration tmpConfig = null;
- for (int i=mActiveResources.size()-1; i>=0; i--) {
+ for (int i = mActiveResources.size() - 1; i >= 0; i--) {
ResourcesKey key = mActiveResources.keyAt(i);
Resources r = mActiveResources.valueAt(i).get();
if (r != null) {
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index 922ebdd..c7d2140 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -19,6 +19,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.StringRes;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -682,6 +683,7 @@
* @return A resource id, or {@code 0} if no language model was specified.
* @see android.R.styleable#Searchable_voiceLanguageModel
*/
+ @StringRes
public int getVoiceLanguageModeId() {
return mVoiceLanguageModeId;
}
@@ -692,6 +694,7 @@
* @return A resource id, or {@code 0} if no voice prompt text was specified.
* @see android.R.styleable#Searchable_voicePromptText
*/
+ @StringRes
public int getVoicePromptTextId() {
return mVoicePromptTextId;
}
@@ -702,6 +705,7 @@
* @return A resource id, or {@code 0} if no language was specified.
* @see android.R.styleable#Searchable_voiceLanguage
*/
+ @StringRes
public int getVoiceLanguageId() {
return mVoiceLanguageId;
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index c8e0031..21a3543 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.Nullable;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Intent;
@@ -498,6 +499,7 @@
* @return Return an IBinder through which clients can call on to the
* service.
*/
+ @Nullable
public abstract IBinder onBind(Intent intent);
/**
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0a255f7..0f6ce12 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -219,10 +219,9 @@
}
/**
- * Returns the currently configured night mode.
- *
- * @return {@link #MODE_NIGHT_NO}, {@link #MODE_NIGHT_YES}, or
- * {@link #MODE_NIGHT_AUTO}. When an error occurred -1 is returned.
+ * @return the currently configured night mode. May be one of
+ * {@link #MODE_NIGHT_NO}, {@link #MODE_NIGHT_YES},
+ * {@link #MODE_NIGHT_AUTO}, or -1 on error.
*/
public int getNightMode() {
if (mService != null) {
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 90d84ee..dcbd669 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.RawRes;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -707,7 +708,7 @@
* @throws IOException If an error occurs reverting to the built-in
* wallpaper.
*/
- public void setResource(int resid) throws IOException {
+ public void setResource(@RawRes int resid) throws IOException {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return;
@@ -823,7 +824,7 @@
* with the given resource ID. That is, their wallpaper has been
* set through {@link #setResource(int)} with the same resource id.
*/
- public boolean hasResourceWallpaper(int resid) {
+ public boolean hasResourceWallpaper(@RawRes int resid) {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
return false;
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 3074b49..d1e40ae 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -165,15 +165,24 @@
/** @hide */
public static class PolicyInfo {
public final int ident;
- final public String tag;
- final public int label;
- final public int description;
+ public final String tag;
+ public final int label;
+ public final int description;
+ public final int labelForSecondaryUsers;
+ public final int descriptionForSecondaryUsers;
- public PolicyInfo(int identIn, String tagIn, int labelIn, int descriptionIn) {
- ident = identIn;
- tag = tagIn;
- label = labelIn;
- description = descriptionIn;
+ public PolicyInfo(int ident, String tag, int label, int description) {
+ this(ident, tag, label, description, label, description);
+ }
+
+ public PolicyInfo(int ident, String tag, int label, int description,
+ int labelForSecondaryUsers, int descriptionForSecondaryUsers) {
+ this.ident = ident;
+ this.tag = tag;
+ this.label = label;
+ this.description = description;
+ this.labelForSecondaryUsers = labelForSecondaryUsers;
+ this.descriptionForSecondaryUsers = descriptionForSecondaryUsers;
}
}
@@ -184,7 +193,10 @@
static {
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data",
com.android.internal.R.string.policylab_wipeData,
- com.android.internal.R.string.policydesc_wipeData));
+ com.android.internal.R.string.policydesc_wipeData,
+ com.android.internal.R.string.policylab_wipeData_secondaryUser,
+ com.android.internal.R.string.policydesc_wipeData_secondaryUser
+ ));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_RESET_PASSWORD, "reset-password",
com.android.internal.R.string.policylab_resetPassword,
com.android.internal.R.string.policydesc_resetPassword));
@@ -193,7 +205,10 @@
com.android.internal.R.string.policydesc_limitPassword));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WATCH_LOGIN, "watch-login",
com.android.internal.R.string.policylab_watchLogin,
- com.android.internal.R.string.policydesc_watchLogin));
+ com.android.internal.R.string.policydesc_watchLogin,
+ com.android.internal.R.string.policylab_watchLogin,
+ com.android.internal.R.string.policydesc_watchLogin_secondaryUser
+ ));
sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock",
com.android.internal.R.string.policylab_forceLock,
com.android.internal.R.string.policydesc_forceLock));
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index e9cce51..9a8dc52 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.security.KeyChain;
/**
* Base class for implementing a device administration component. This
@@ -170,10 +171,10 @@
* lock task mode from an authorized package. The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
* will describe the authorized package using lock task mode.
*
- * @see DevicePolicyManager#isLockTaskPermitted(String)
- *
* <p>The calling device admin must be the device owner or profile
* owner to receive this broadcast.
+ *
+ * @see DevicePolicyManager#isLockTaskPermitted(String)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_ENTERING
@@ -183,20 +184,19 @@
* Action sent to a device administrator to notify that the device is exiting
* lock task mode from an authorized package.
*
- * @see DevicePolicyManager#isLockTaskPermitted(String)
- *
* <p>The calling device admin must be the device owner or profile
* owner to receive this broadcast.
+ *
+ * @see DevicePolicyManager#isLockTaskPermitted(String)
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_EXITING
= "android.app.action.LOCK_TASK_EXITING";
/**
- * A boolean describing whether the device is currently entering or exiting
- * lock task mode.
+ * A string containing the name of the package entering lock task mode.
*
- * @see #ACTION_LOCK_TASK_CHANGED
+ * @see #ACTION_LOCK_TASK_ENTERING
*/
public static final String EXTRA_LOCK_TASK_PACKAGE =
"android.app.extra.LOCK_TASK_PACKAGE";
@@ -223,7 +223,28 @@
public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
"android.app.action.PROFILE_PROVISIONING_COMPLETE";
- /**
+ /** @hide */
+ public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID = "android.app.extra.CHOOSE_PRIVATE_KEY_SENDER_UID";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_HOST = "android.app.extra.CHOOSE_PRIVATE_KEY_HOST";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_PORT = "android.app.extra.CHOOSE_PRIVATE_KEY_PORT";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_URL = "android.app.extra.CHOOSE_PRIVATE_KEY_URL";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.extra.CHOOSE_PRIVATE_KEY_ALIAS";
+
+ /** @hide */
+ public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
+
+ /**
* Name under which a DevicePolicy component publishes information
* about itself. This meta-data must reference an XML resource containing
* a device-admin tag. XXX TO DO: describe syntax.
@@ -403,6 +424,26 @@
}
/**
+ * Allows this receiver to select the alias for a private key and certificate pair for
+ * authentication. If this method returns null, the default {@link android.app.Activity} will be
+ * shown that lets the user pick a private key and certificate pair.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @param uid The uid asking for the private key and certificate pair.
+ * @param host The authentication host, may be null.
+ * @param port The authentication port, or -1.
+ * @param url The URL to authenticate, may be null.
+ * @param alias The alias preselected by the client, or null.
+ * @return The private key alias to return and grant access to.
+ * @see KeyChain#choosePrivateKeyAlias
+ */
+ public String onChoosePrivateKeyAlias(Context context, Intent intent, int uid, String host,
+ int port, String url, String alias) {
+ return null;
+ }
+
+ /**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
* convenience callbacks for each action.
@@ -431,6 +472,15 @@
onPasswordExpiring(context, intent);
} else if (ACTION_PROFILE_PROVISIONING_COMPLETE.equals(action)) {
onProfileProvisioningComplete(context, intent);
+ } else if (ACTION_CHOOSE_PRIVATE_KEY_ALIAS.equals(action)) {
+ int uid = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, -1);
+ String host = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_HOST);
+ int port = intent.getIntExtra(EXTRA_CHOOSE_PRIVATE_KEY_PORT, -1);
+ String url = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_URL);
+ String alias = intent.getStringExtra(EXTRA_CHOOSE_PRIVATE_KEY_ALIAS);
+ String chosenAlias = onChoosePrivateKeyAlias(context, intent, uid, host, port, url,
+ alias);
+ setResultData(chosenAlias);
} else if (ACTION_LOCK_TASK_ENTERING.equals(action)) {
String pkg = intent.getStringExtra(EXTRA_LOCK_TASK_PACKAGE);
onLockTaskModeEntering(context, intent, pkg);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 318a314..c5b6320 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -111,9 +111,11 @@
*
* <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
*
- * <p> When managed provisioning has completed, an intent of the type
- * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcasted to the
- * managed profile.
+ * <p> When managed provisioning has completed, broadcasts are sent to the application specified
+ * in the provisioning intent. The
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} broadcast is sent in the
+ * managed profile and the {@link #ACTION_MANAGED_PROFILE_PROVISIONED} broadcast is sent in
+ * the primary profile.
*
* <p> If provisioning fails, the managedProfile is removed so the device returns to its
* previous state.
@@ -332,6 +334,20 @@
= "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
/**
+ * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
+ * has completed successfully.
+ *
+ * <p>The broadcast is limited to the primary profile, to the app specified in the provisioning
+ * intent (@see #ACTION_PROVISION_MANAGED_PROFILE).
+ *
+ * <p>This intent will contain the extra {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE} which
+ * corresponds to the account requested to be migrated at provisioning time, if any.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGED_PROFILE_PROVISIONED
+ = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+
+ /**
* A boolean extra indicating whether device encryption is required as part of Device Owner
* provisioning.
*
@@ -2694,6 +2710,7 @@
* <p>If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all admins,
* then it's up to the TrustAgent itself to aggregate the values from all device admins.
* <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
+ * @hide
*/
public void setTrustAgentConfiguration(ComponentName admin, ComponentName target,
PersistableBundle configuration) {
@@ -2719,6 +2736,7 @@
* for this {@param agent} or calls it with a null configuration, null is returned.
* @param agent Which component to get enabled features for.
* @return configuration for the given trust agent.
+ * @hide
*/
public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
ComponentName agent) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 67bca4e..714e740 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -129,6 +129,7 @@
void enforceCanManageCaCerts(in ComponentName admin);
boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias);
+ void choosePrivateKeyAlias(int uid, in String host, int port, in String url, in String alias, IBinder aliasCallback);
void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index dec2524..46ccc95 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -20,6 +20,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.StringRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
import android.annotation.SystemApi;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -365,7 +368,7 @@
*
* @param resId Resource id for the CharSequence text
*/
- public final CharSequence getText(int resId) {
+ public final CharSequence getText(@StringRes int resId) {
return getResources().getText(resId);
}
@@ -375,7 +378,7 @@
*
* @param resId Resource id for the string
*/
- public final String getString(int resId) {
+ public final String getString(@StringRes int resId) {
return getResources().getString(resId);
}
@@ -388,7 +391,7 @@
* @param formatArgs The format arguments that will be used for substitution.
*/
- public final String getString(int resId, Object... formatArgs) {
+ public final String getString(@StringRes int resId, Object... formatArgs) {
return getResources().getString(resId, formatArgs);
}
@@ -450,7 +453,7 @@
*
* @param resid The style resource describing the theme.
*/
- public abstract void setTheme(int resid);
+ public abstract void setTheme(@StyleRes int resid);
/** @hide Needed for some internal implementation... not public because
* you can't assume this actually means anything. */
@@ -484,7 +487,7 @@
* @see Resources.Theme#obtainStyledAttributes(int, int[])
*/
public final TypedArray obtainStyledAttributes(
- int resid, int[] attrs) throws Resources.NotFoundException {
+ @StyleableRes int resid, int[] attrs) throws Resources.NotFoundException {
return getTheme().obtainStyledAttributes(resid, attrs);
}
@@ -2149,17 +2152,21 @@
WIFI_PASSPOINT_SERVICE,
WIFI_P2P_SERVICE,
WIFI_SCANNING_SERVICE,
+ //@hide: WIFI_RTT_SERVICE,
//@hide: ETHERNET_SERVICE,
WIFI_RTT_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
+ //@hide: FINGERPRINT_SERVICE,
MEDIA_ROUTER_SERVICE,
TELEPHONY_SERVICE,
+ TELEPHONY_SUBSCRIPTION_SERVICE,
TELECOM_SERVICE,
CLIPBOARD_SERVICE,
INPUT_METHOD_SERVICE,
TEXT_SERVICES_MANAGER_SERVICE,
APPWIDGET_SERVICE,
+ //@hide: VOICE_INTERACTION_MANAGER_SERVICE,
//@hide: BACKUP_SERVICE,
DROPBOX_SERVICE,
DEVICE_POLICY_SERVICE,
@@ -2171,16 +2178,23 @@
USB_SERVICE,
LAUNCHER_APPS_SERVICE,
//@hide: SERIAL_SERVICE,
+ //@hide: HDMI_CONTROL_SERVICE,
INPUT_SERVICE,
DISPLAY_SERVICE,
- //@hide: SCHEDULING_POLICY_SERVICE,
USER_SERVICE,
- //@hide: APP_OPS_SERVICE
+ RESTRICTIONS_SERVICE,
+ APP_OPS_SERVICE,
CAMERA_SERVICE,
PRINT_SERVICE,
+ CONSUMER_IR_SERVICE,
+ //@hide: TRUST_SERVICE,
+ TV_INPUT_SERVICE,
+ //@hide: NETWORK_SCORE_SERVICE,
+ USAGE_STATS_SERVICE,
MEDIA_SESSION_SERVICE,
BATTERY_SERVICE,
JOB_SCHEDULER_SERVICE,
+ //@hide: PERSISTENT_DATA_BLOCK_SERVICE,
MEDIA_PROJECTION_SERVICE,
MIDI_SERVICE,
})
@@ -2957,7 +2971,7 @@
/**
* Use with {@link #getSystemService} to retrieve a
- * {@link android.midi.MidiManager} for accessing the MIDI service.
+ * {@link android.media.midi.MidiManager} for accessing the MIDI service.
*
* @see #getSystemService
* @hide
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 582802b..3222b2b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -23,6 +23,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnyRes;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
@@ -762,11 +763,11 @@
* identifier.
*
* @param context The context of the application.
- * @param resourceId The resource idenfitier for the icon.
+ * @param resourceId The resource identifier for the icon.
* @return A new ShortcutIconResource with the specified's context package name
- * and icon resource idenfitier.
+ * and icon resource identifier.``
*/
- public static ShortcutIconResource fromContext(Context context, int resourceId) {
+ public static ShortcutIconResource fromContext(Context context, @AnyRes int resourceId) {
ShortcutIconResource icon = new ShortcutIconResource();
icon.packageName = context.getPackageName();
icon.resourceName = context.getResources().getResourceName(resourceId);
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 5341ea8..6d79626 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.ArrayRes;
import android.os.Parcel;
import android.os.Parcelable;
@@ -277,7 +278,7 @@
* @param stringArrayResId the resource id for a string array containing the possible values.
* @see #setChoiceValues(String[])
*/
- public void setChoiceValues(Context context, int stringArrayResId) {
+ public void setChoiceValues(Context context, @ArrayRes int stringArrayResId) {
mChoiceValues = context.getResources().getStringArray(stringArrayResId);
}
@@ -307,7 +308,7 @@
* @param context the application context, used for retrieving the resources.
* @param stringArrayResId the resource id of a string array containing the possible entries.
*/
- public void setChoiceEntries(Context context, int stringArrayResId) {
+ public void setChoiceEntries(Context context, @ArrayRes int stringArrayResId) {
mChoiceEntries = context.getResources().getStringArray(stringArrayResId);
}
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index cd32dae..1d16516 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -73,9 +73,7 @@
* {@link #commit} or {@link #apply} are called.
*
* @param key The name of the preference to modify.
- * @param value The new value for the preference. Supplying {@code null}
- * as the value is equivalent to calling {@link #remove(String)} with
- * this key.
+ * @param value The new value for the preference.
*
* @return Returns a reference to the same Editor object, so you can
* chain put calls together.
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index e9ec5a4..e3bc238 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -20,9 +20,9 @@
import android.os.Parcelable;
import android.os.ParcelableParcel;
import android.text.TextUtils;
+import android.util.ArrayMap;
import java.util.ArrayList;
-import java.util.HashMap;
/**
* Top-level class for managing and interacting with the global undo state for
@@ -54,7 +54,9 @@
* @hide
*/
public class UndoManager {
- private final HashMap<String, UndoOwner> mOwners = new HashMap<String, UndoOwner>();
+ // The common case is a single undo owner (e.g. for a TextView), so default to that capacity.
+ private final ArrayMap<String, UndoOwner> mOwners =
+ new ArrayMap<String, UndoOwner>(1 /* capacity */);
private final ArrayList<UndoState> mUndos = new ArrayList<UndoState>();
private final ArrayList<UndoState> mRedos = new ArrayList<UndoState>();
private int mUpdateCount;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e9f7c50..ebc8e1e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,11 +16,14 @@
package android.content.pm;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringRes;
import android.annotation.SystemApi;
+import android.annotation.XmlRes;
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
@@ -2710,7 +2713,7 @@
* @return Returns a Drawable holding the requested image. Returns null if
* an image could not be found for any reason.
*/
- public abstract Drawable getDrawable(String packageName, int resid,
+ public abstract Drawable getDrawable(String packageName, @DrawableRes int resid,
ApplicationInfo appInfo);
/**
@@ -3012,7 +3015,7 @@
* @return Returns a CharSequence holding the requested text. Returns null
* if the text could not be found for any reason.
*/
- public abstract CharSequence getText(String packageName, int resid,
+ public abstract CharSequence getText(String packageName, @StringRes int resid,
ApplicationInfo appInfo);
/**
@@ -3031,7 +3034,7 @@
* data. Returns null if the xml resource could not be found for any
* reason.
*/
- public abstract XmlResourceParser getXml(String packageName, int resid,
+ public abstract XmlResourceParser getXml(String packageName, @XmlRes int resid,
ApplicationInfo appInfo);
/**
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index a386097..c2d2f65 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -27,6 +27,7 @@
import android.os.Environment;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.AtomicFile;
import android.util.AttributeSet;
import android.util.Log;
@@ -47,9 +48,9 @@
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -74,6 +75,7 @@
public abstract class RegisteredServicesCache<V> {
private static final String TAG = "PackageManager";
private static final boolean DEBUG = false;
+ protected static final String REGISTERED_SERVICES_DIR = "registered_services";
public final Context mContext;
private final String mInterfaceName;
@@ -84,57 +86,67 @@
private final Object mServicesLock = new Object();
@GuardedBy("mServicesLock")
- private boolean mPersistentServicesFileDidNotExist;
- @GuardedBy("mServicesLock")
private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>(2);
private static class UserServices<V> {
@GuardedBy("mServicesLock")
- public final Map<V, Integer> persistentServices = Maps.newHashMap();
+ final Map<V, Integer> persistentServices = Maps.newHashMap();
@GuardedBy("mServicesLock")
- public Map<V, ServiceInfo<V>> services = null;
+ Map<V, ServiceInfo<V>> services = null;
+ @GuardedBy("mServicesLock")
+ boolean mPersistentServicesFileDidNotExist = true;
}
+ @GuardedBy("mServicesLock")
private UserServices<V> findOrCreateUserLocked(int userId) {
+ return findOrCreateUserLocked(userId, true);
+ }
+
+ @GuardedBy("mServicesLock")
+ private UserServices<V> findOrCreateUserLocked(int userId, boolean loadFromFileIfNew) {
UserServices<V> services = mUserServices.get(userId);
if (services == null) {
services = new UserServices<V>();
mUserServices.put(userId, services);
+ if (loadFromFileIfNew && mSerializerAndParser != null) {
+ // Check if user exists and try loading data from file
+ // clear existing data if there was an error during migration
+ UserInfo user = getUser(userId);
+ if (user != null) {
+ AtomicFile file = createFileForUser(user.id);
+ if (file.getBaseFile().exists()) {
+ if (DEBUG) {
+ Slog.i(TAG, String.format("Loading u%s data from %s", user.id, file));
+ }
+ InputStream is = null;
+ try {
+ is = file.openRead();
+ readPersistentServicesLocked(is);
+ } catch (Exception e) {
+ Log.w(TAG, "Error reading persistent services for user " + user.id, e);
+ } finally {
+ IoUtils.closeQuietly(is);
+ }
+ }
+ }
+ }
}
return services;
}
- /**
- * This file contains the list of known services. We would like to maintain this forever
- * so we store it as an XML file.
- */
- private final AtomicFile mPersistentServicesFile;
-
// the listener and handler are synchronized on "this" and must be updated together
private RegisteredServicesCacheListener<V> mListener;
private Handler mHandler;
public RegisteredServicesCache(Context context, String interfaceName, String metaDataName,
String attributeName, XmlSerializerAndParser<V> serializerAndParser) {
- this(context, interfaceName, metaDataName, attributeName, serializerAndParser,
- Environment.getDataDirectory());
- }
-
- @VisibleForTesting
- protected RegisteredServicesCache(Context context, String interfaceName, String metaDataName,
- String attributeName, XmlSerializerAndParser<V> serializerAndParser, File dataDir) {
mContext = context;
mInterfaceName = interfaceName;
mMetaDataName = metaDataName;
mAttributesName = attributeName;
mSerializerAndParser = serializerAndParser;
- File systemDir = new File(dataDir, "system");
- File syncDir = new File(systemDir, "registered_services");
- mPersistentServicesFile = new AtomicFile(new File(syncDir, interfaceName + ".xml"));
-
- // Load persisted services from disk
- readPersistentServicesLocked();
+ migrateIfNecessaryLocked();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -148,6 +160,11 @@
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mExternalReceiver, sdFilter);
+
+ // Register for user-related events
+ IntentFilter userFilter = new IntentFilter();
+ sdFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(mUserRemovedReceiver, userFilter);
}
private final void handlePackageEvent(Intent intent, int userId) {
@@ -199,6 +216,17 @@
}
};
+ private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (DEBUG) {
+ Slog.d(TAG, "u" + userId + " removed - cleaning up");
+ }
+ onUserRemoved(userId);
+ }
+ };
+
public void invalidateCache(int userId) {
synchronized (mServicesLock) {
final UserServices<V> user = findOrCreateUserLocked(userId);
@@ -390,7 +418,7 @@
changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
- if (!(mPersistentServicesFileDidNotExist && firstScan)) {
+ if (!(user.mPersistentServicesFileDidNotExist && firstScan)) {
notifyListener(info.type, userId, false /* removed */);
}
} else if (previousUid == info.uid) {
@@ -460,7 +488,7 @@
}
}
if (changed) {
- writePersistentServicesLocked();
+ writePersistentServicesLocked(user, userId);
}
}
}
@@ -542,89 +570,152 @@
/**
* Read all sync status back in to the initial engine state.
*/
- private void readPersistentServicesLocked() {
- mUserServices.clear();
+ private void readPersistentServicesLocked(InputStream is)
+ throws XmlPullParserException, IOException {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(is, null);
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.START_TAG
+ && eventType != XmlPullParser.END_DOCUMENT) {
+ eventType = parser.next();
+ }
+ String tagName = parser.getName();
+ if ("services".equals(tagName)) {
+ eventType = parser.next();
+ do {
+ if (eventType == XmlPullParser.START_TAG && parser.getDepth() == 2) {
+ tagName = parser.getName();
+ if ("service".equals(tagName)) {
+ V service = mSerializerAndParser.createFromXml(parser);
+ if (service == null) {
+ break;
+ }
+ String uidString = parser.getAttributeValue(null, "uid");
+ final int uid = Integer.parseInt(uidString);
+ final int userId = UserHandle.getUserId(uid);
+ final UserServices<V> user = findOrCreateUserLocked(userId,
+ false /*loadFromFileIfNew*/) ;
+ user.persistentServices.put(service, uid);
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+ }
+ }
+
+ private void migrateIfNecessaryLocked() {
if (mSerializerAndParser == null) {
return;
}
- FileInputStream fis = null;
- try {
- mPersistentServicesFileDidNotExist = !mPersistentServicesFile.getBaseFile().exists();
- if (mPersistentServicesFileDidNotExist) {
- return;
- }
- fis = mPersistentServicesFile.openRead();
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(fis, null);
- int eventType = parser.getEventType();
- while (eventType != XmlPullParser.START_TAG
- && eventType != XmlPullParser.END_DOCUMENT) {
- eventType = parser.next();
- }
- String tagName = parser.getName();
- if ("services".equals(tagName)) {
- eventType = parser.next();
- do {
- if (eventType == XmlPullParser.START_TAG && parser.getDepth() == 2) {
- tagName = parser.getName();
- if ("service".equals(tagName)) {
- V service = mSerializerAndParser.createFromXml(parser);
- if (service == null) {
- break;
+ File systemDir = new File(getDataDirectory(), "system");
+ File syncDir = new File(systemDir, REGISTERED_SERVICES_DIR);
+ AtomicFile oldFile = new AtomicFile(new File(syncDir, mInterfaceName + ".xml"));
+ boolean oldFileExists = oldFile.getBaseFile().exists();
+
+ if (oldFileExists) {
+ File marker = new File(syncDir, mInterfaceName + ".xml.migrated");
+ // if not migrated, perform the migration and add a marker
+ if (!marker.exists()) {
+ if (DEBUG) {
+ Slog.i(TAG, "Marker file " + marker + " does not exist - running migration");
+ }
+ InputStream is = null;
+ try {
+ is = oldFile.openRead();
+ mUserServices.clear();
+ readPersistentServicesLocked(is);
+ } catch (Exception e) {
+ Log.w(TAG, "Error reading persistent services, starting from scratch", e);
+ } finally {
+ IoUtils.closeQuietly(is);
+ }
+ try {
+ for (UserInfo user : getUsers()) {
+ UserServices<V> userServices = mUserServices.get(user.id);
+ if (userServices != null) {
+ if (DEBUG) {
+ Slog.i(TAG, "Migrating u" + user.id + " services "
+ + userServices.persistentServices);
}
- String uidString = parser.getAttributeValue(null, "uid");
- final int uid = Integer.parseInt(uidString);
- final int userId = UserHandle.getUserId(uid);
- final UserServices<V> user = findOrCreateUserLocked(userId);
- user.persistentServices.put(service, uid);
+ writePersistentServicesLocked(userServices, user.id);
}
}
- eventType = parser.next();
- } while (eventType != XmlPullParser.END_DOCUMENT);
+ marker.createNewFile();
+ } catch (Exception e) {
+ Log.w(TAG, "Migration failed", e);
+ }
+ // Migration is complete and we don't need to keep data for all users anymore,
+ // It will be loaded from a new location when requested
+ mUserServices.clear();
}
- } catch (Exception e) {
- Log.w(TAG, "Error reading persistent services, starting from scratch", e);
- } finally {
- IoUtils.closeQuietly(fis);
}
}
/**
- * Write all sync status to the sync status file.
+ * Writes services of a specified user to the file.
*/
- private void writePersistentServicesLocked() {
+ private void writePersistentServicesLocked(UserServices<V> user, int userId) {
if (mSerializerAndParser == null) {
return;
}
+ AtomicFile atomicFile = createFileForUser(userId);
FileOutputStream fos = null;
try {
- fos = mPersistentServicesFile.startWrite();
+ fos = atomicFile.startWrite();
XmlSerializer out = new FastXmlSerializer();
out.setOutput(fos, "utf-8");
out.startDocument(null, true);
out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
out.startTag(null, "services");
- for (int i = 0; i < mUserServices.size(); i++) {
- final UserServices<V> user = mUserServices.valueAt(i);
- for (Map.Entry<V, Integer> service : user.persistentServices.entrySet()) {
- out.startTag(null, "service");
- out.attribute(null, "uid", Integer.toString(service.getValue()));
- mSerializerAndParser.writeAsXml(service.getKey(), out);
- out.endTag(null, "service");
- }
+ for (Map.Entry<V, Integer> service : user.persistentServices.entrySet()) {
+ out.startTag(null, "service");
+ out.attribute(null, "uid", Integer.toString(service.getValue()));
+ mSerializerAndParser.writeAsXml(service.getKey(), out);
+ out.endTag(null, "service");
}
out.endTag(null, "services");
out.endDocument();
- mPersistentServicesFile.finishWrite(fos);
+ atomicFile.finishWrite(fos);
} catch (IOException e1) {
Log.w(TAG, "Error writing accounts", e1);
if (fos != null) {
- mPersistentServicesFile.failWrite(fos);
+ atomicFile.failWrite(fos);
}
}
}
@VisibleForTesting
+ protected void onUserRemoved(int userId) {
+ mUserServices.remove(userId);
+ }
+
+ @VisibleForTesting
+ protected List<UserInfo> getUsers() {
+ return UserManager.get(mContext).getUsers(true);
+ }
+
+ @VisibleForTesting
+ protected UserInfo getUser(int userId) {
+ return UserManager.get(mContext).getUserInfo(userId);
+ }
+
+ private AtomicFile createFileForUser(int userId) {
+ File userDir = getUserSystemDirectory(userId);
+ File userFile = new File(userDir, REGISTERED_SERVICES_DIR + "/" + mInterfaceName + ".xml");
+ return new AtomicFile(userFile);
+ }
+
+ @VisibleForTesting
+ protected File getUserSystemDirectory(int userId) {
+ return Environment.getUserSystemDirectory(userId);
+ }
+
+ @VisibleForTesting
+ protected File getDataDirectory() {
+ return Environment.getDataDirectory();
+ }
+
+ @VisibleForTesting
protected Map<V, Integer> getPersistentServices(int userId) {
return findOrCreateUserLocked(userId).persistentServices;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 6fb7299..3e922f2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -23,8 +23,22 @@
import android.animation.Animator;
import android.animation.StateListAnimator;
+import android.annotation.AnimRes;
+import android.annotation.AnyRes;
+import android.annotation.ArrayRes;
+import android.annotation.BoolRes;
+import android.annotation.ColorRes;
+import android.annotation.DimenRes;
+import android.annotation.DrawableRes;
+import android.annotation.FractionRes;
+import android.annotation.IntegerRes;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PluralsRes;
+import android.annotation.RawRes;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList.ColorStateListFactory;
import android.graphics.Movie;
@@ -287,7 +301,7 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getText(int id) throws NotFoundException {
+ public CharSequence getText(@StringRes int id) throws NotFoundException {
CharSequence res = mAssets.getResourceText(id);
if (res != null) {
return res;
@@ -316,7 +330,8 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getQuantityText(int id, int quantity) throws NotFoundException {
+ public CharSequence getQuantityText(@PluralsRes int id, int quantity)
+ throws NotFoundException {
NativePluralRules rule = getPluralRule();
CharSequence res = mAssets.getResourceBagText(id,
attrForQuantityCode(rule.quantityForInt(quantity)));
@@ -377,7 +392,7 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getString(int id) throws NotFoundException {
+ public String getString(@StringRes int id) throws NotFoundException {
CharSequence res = getText(id);
if (res != null) {
return res.toString();
@@ -405,7 +420,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getString(int id, Object... formatArgs) throws NotFoundException {
+ public String getString(@StringRes int id, Object... formatArgs)
+ throws NotFoundException {
String raw = getString(id);
return String.format(mConfiguration.locale, raw, formatArgs);
}
@@ -435,7 +451,7 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(int id, int quantity, Object... formatArgs)
+ public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
throws NotFoundException {
String raw = getQuantityText(id, quantity).toString();
return String.format(mConfiguration.locale, raw, formatArgs);
@@ -461,7 +477,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(int id, int quantity) throws NotFoundException {
+ public String getQuantityString(@PluralsRes int id, int quantity)
+ throws NotFoundException {
return getQuantityText(id, quantity).toString();
}
@@ -479,7 +496,7 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information, or def if id is 0 or not found.
*/
- public CharSequence getText(int id, CharSequence def) {
+ public CharSequence getText(@StringRes int id, CharSequence def) {
CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
return res != null ? res : def;
}
@@ -495,7 +512,7 @@
*
* @return The styled text array associated with the resource.
*/
- public CharSequence[] getTextArray(int id) throws NotFoundException {
+ public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
CharSequence[] res = mAssets.getResourceTextArray(id);
if (res != null) {
return res;
@@ -515,7 +532,8 @@
*
* @return The string array associated with the resource.
*/
- public String[] getStringArray(int id) throws NotFoundException {
+ public String[] getStringArray(@ArrayRes int id)
+ throws NotFoundException {
String[] res = mAssets.getResourceStringArray(id);
if (res != null) {
return res;
@@ -535,7 +553,7 @@
*
* @return The int array associated with the resource.
*/
- public int[] getIntArray(int id) throws NotFoundException {
+ public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
int[] res = mAssets.getArrayIntResource(id);
if (res != null) {
return res;
@@ -557,7 +575,8 @@
* Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
* when done with it.
*/
- public TypedArray obtainTypedArray(int id) throws NotFoundException {
+ public TypedArray obtainTypedArray(@ArrayRes int id)
+ throws NotFoundException {
int len = mAssets.getArraySize(id);
if (len < 0) {
throw new NotFoundException("Array resource ID #0x"
@@ -588,7 +607,7 @@
* @see #getDimensionPixelOffset
* @see #getDimensionPixelSize
*/
- public float getDimension(int id) throws NotFoundException {
+ public float getDimension(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -623,7 +642,7 @@
* @see #getDimension
* @see #getDimensionPixelSize
*/
- public int getDimensionPixelOffset(int id) throws NotFoundException {
+ public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -660,7 +679,7 @@
* @see #getDimension
* @see #getDimensionPixelOffset
*/
- public int getDimensionPixelSize(int id) throws NotFoundException {
+ public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -694,7 +713,7 @@
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
- public float getFraction(int id, int base, int pbase) {
+ public float getFraction(@FractionRes int id, int base, int pbase) {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -744,7 +763,7 @@
*/
@Deprecated
@Nullable
- public Drawable getDrawable(int id) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
final Drawable d = getDrawable(id, null);
if (d != null && d.canApplyTheme()) {
Log.w(TAG, "Drawable " + getResourceName(id) + " has unresolved theme "
@@ -769,7 +788,7 @@
* not exist.
*/
@Nullable
- public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -817,7 +836,7 @@
*/
@Deprecated
@Nullable
- public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density) throws NotFoundException {
return getDrawableForDensity(id, density, null);
}
@@ -836,7 +855,7 @@
* not exist.
*/
@Nullable
- public Drawable getDrawableForDensity(int id, int density, @Nullable Theme theme) {
+ public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -880,7 +899,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public Movie getMovie(int id) throws NotFoundException {
+ public Movie getMovie(@RawRes int id) throws NotFoundException {
InputStream is = openRawResource(id);
Movie movie = Movie.decodeStream(is);
try {
@@ -907,7 +926,7 @@
* @return A single color value in the form 0xAARRGGBB.
* @deprecated Use {@link #getColor(int, Theme)} instead.
*/
- public int getColor(int id) throws NotFoundException {
+ public int getColor(@ColorRes int id) throws NotFoundException {
return getColor(id, null);
}
@@ -927,7 +946,7 @@
*
* @return A single color value in the form 0xAARRGGBB.
*/
- public int getColor(int id, @Nullable Theme theme) throws NotFoundException {
+ public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -975,7 +994,7 @@
* @deprecated Use {@link #getColorStateList(int, Theme)} instead.
*/
@Nullable
- public ColorStateList getColorStateList(int id) throws NotFoundException {
+ public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
final ColorStateList csl = getColorStateList(id, null);
if (csl != null && csl.canApplyTheme()) {
Log.w(TAG, "ColorStateList " + getResourceName(id) + " has "
@@ -1005,7 +1024,7 @@
* color or multiple colors that can be selected based on a state.
*/
@Nullable
- public ColorStateList getColorStateList(int id, @Nullable Theme theme)
+ public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
@@ -1043,7 +1062,7 @@
*
* @return Returns the boolean value contained in the resource.
*/
- public boolean getBoolean(int id) throws NotFoundException {
+ public boolean getBoolean(@BoolRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -1071,7 +1090,7 @@
*
* @return Returns the integer value contained in the resource.
*/
- public int getInteger(int id) throws NotFoundException {
+ public int getInteger(@IntegerRes int id) throws NotFoundException {
synchronized (mAccessLock) {
TypedValue value = mTmpValue;
if (value == null) {
@@ -1136,7 +1155,7 @@
*
* @see #getXml
*/
- public XmlResourceParser getLayout(int id) throws NotFoundException {
+ public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "layout");
}
@@ -1160,7 +1179,7 @@
*
* @see #getXml
*/
- public XmlResourceParser getAnimation(int id) throws NotFoundException {
+ public XmlResourceParser getAnimation(@AnimRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "anim");
}
@@ -1185,7 +1204,7 @@
*
* @see android.util.AttributeSet
*/
- public XmlResourceParser getXml(int id) throws NotFoundException {
+ public XmlResourceParser getXml(@XmlRes int id) throws NotFoundException {
return loadXmlResourceParser(id, "xml");
}
@@ -1203,7 +1222,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public InputStream openRawResource(int id) throws NotFoundException {
+ public InputStream openRawResource(@RawRes int id) throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -1235,7 +1254,8 @@
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
- public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
+ public InputStream openRawResource(@RawRes int id, TypedValue value)
+ throws NotFoundException {
getValue(id, value, true);
try {
@@ -1270,7 +1290,8 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
+ public AssetFileDescriptor openRawResourceFd(@RawRes int id)
+ throws NotFoundException {
TypedValue value;
synchronized (mAccessLock) {
value = mTmpValue;
@@ -1315,7 +1336,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
*/
- public void getValue(int id, TypedValue outValue, boolean resolveRefs)
+ public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
@@ -1338,8 +1359,8 @@
* not exist.
* @see #getValue(String, TypedValue, boolean)
*/
- public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
+ public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+ boolean resolveRefs) throws NotFoundException {
boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
if (found) {
return;
@@ -1698,7 +1719,7 @@
* @throws NotFoundException Throws NotFoundException if the given ID
* does not exist.
*/
- public Drawable getDrawable(int id) throws NotFoundException {
+ public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
return Resources.this.getDrawable(id, this);
}
@@ -2103,7 +2124,7 @@
*
* @hide
*/
- public static boolean resourceHasPackage(int resid) {
+ public static boolean resourceHasPackage(@AnyRes int resid) {
return (resid >>> 24) != 0;
}
@@ -2121,7 +2142,7 @@
* @see #getResourceTypeName
* @see #getResourceEntryName
*/
- public String getResourceName(int resid) throws NotFoundException {
+ public String getResourceName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2140,7 +2161,7 @@
*
* @see #getResourceName
*/
- public String getResourcePackageName(int resid) throws NotFoundException {
+ public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourcePackageName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2159,7 +2180,7 @@
*
* @see #getResourceName
*/
- public String getResourceTypeName(int resid) throws NotFoundException {
+ public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceTypeName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
@@ -2178,7 +2199,7 @@
*
* @see #getResourceName
*/
- public String getResourceEntryName(int resid) throws NotFoundException {
+ public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
String str = mAssets.getResourceEntryName(resid);
if (str != null) return str;
throw new NotFoundException("Unable to find resource ID #0x"
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f15b6b9..3d43304 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -16,6 +16,7 @@
package android.content.res;
+import android.annotation.AnyRes;
import android.annotation.Nullable;
import android.graphics.drawable.Drawable;
import android.os.StrictMode;
@@ -786,6 +787,7 @@
* @return Attribute resource identifier, or defValue if not defined.
* @throws RuntimeException if the TypedArray has already been recycled.
*/
+ @AnyRes
public int getResourceId(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index c125544..e61664c 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -16,8 +16,6 @@
package android.database;
-import org.apache.commons.codec.binary.Hex;
-
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
@@ -416,11 +414,33 @@
* @return the collation key in hex format
*/
public static String getHexCollationKey(String name) {
- byte [] arr = getCollationKeyInBytes(name);
- char[] keys = Hex.encodeHex(arr);
+ byte[] arr = getCollationKeyInBytes(name);
+ char[] keys = encodeHex(arr);
return new String(keys, 0, getKeyLen(arr) * 2);
}
+
+ /**
+ * Used building output as Hex
+ */
+ private static final char[] DIGITS = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+
+ private static char[] encodeHex(byte[] input) {
+ int l = input.length;
+ char[] out = new char[l << 1];
+
+ // two characters form the hex value.
+ for (int i = 0, j = 0; i < l; i++) {
+ out[j++] = DIGITS[(0xF0 & input[i]) >>> 4 ];
+ out[j++] = DIGITS[ 0x0F & input[i] ];
+ }
+
+ return out;
+ }
+
private static int getKeyLen(byte[] arr) {
if (arr[arr.length - 1] != 0) {
return arr.length;
diff --git a/core/java/android/gesture/GestureLibraries.java b/core/java/android/gesture/GestureLibraries.java
index 6d6c156..611d9ab 100644
--- a/core/java/android/gesture/GestureLibraries.java
+++ b/core/java/android/gesture/GestureLibraries.java
@@ -16,6 +16,7 @@
package android.gesture;
+import android.annotation.RawRes;
import android.util.Log;
import static android.gesture.GestureConstants.*;
import android.content.Context;
@@ -44,7 +45,7 @@
return fromFile(context.getFileStreamPath(name));
}
- public static GestureLibrary fromRawResource(Context context, int resourceId) {
+ public static GestureLibrary fromRawResource(Context context, @RawRes int resourceId) {
return new ResourceGestureLibrary(context, resourceId);
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index fa5e9d2..39f4cca 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -833,4 +833,96 @@
+ ", type=" + mType + ", maxRange=" + mMaxRange + ", resolution=" + mResolution
+ ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
}
+
+ /**
+ * Sets the Type associated with the sensor.
+ * NOTE: to be used only by native bindings in SensorManager.
+ *
+ * This allows interned static strings to be used across all representations of the Sensor. If
+ * a sensor type is not referenced here, it will still be interned by the native SensorManager.
+ *
+ * @return {@code true} if the StringType was successfully set, {@code false} otherwise.
+ */
+ private boolean setType(int value) {
+ mType = value;
+ switch (mType) {
+ case TYPE_ACCELEROMETER:
+ mStringType = STRING_TYPE_ACCELEROMETER;
+ return true;
+ case TYPE_AMBIENT_TEMPERATURE:
+ mStringType = STRING_TYPE_AMBIENT_TEMPERATURE;
+ return true;
+ case TYPE_GAME_ROTATION_VECTOR:
+ mStringType = STRING_TYPE_GAME_ROTATION_VECTOR;
+ return true;
+ case TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ mStringType = STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+ return true;
+ case TYPE_GLANCE_GESTURE:
+ mStringType = STRING_TYPE_GLANCE_GESTURE;
+ return true;
+ case TYPE_GRAVITY:
+ mStringType = STRING_TYPE_GRAVITY;
+ return true;
+ case TYPE_GYROSCOPE:
+ mStringType = STRING_TYPE_GYROSCOPE;
+ return true;
+ case TYPE_GYROSCOPE_UNCALIBRATED:
+ mStringType = STRING_TYPE_GYROSCOPE_UNCALIBRATED;
+ return true;
+ case TYPE_HEART_RATE:
+ mStringType = STRING_TYPE_HEART_RATE;
+ return true;
+ case TYPE_LIGHT:
+ mStringType = STRING_TYPE_LIGHT;
+ return true;
+ case TYPE_LINEAR_ACCELERATION:
+ mStringType = STRING_TYPE_LINEAR_ACCELERATION;
+ return true;
+ case TYPE_MAGNETIC_FIELD:
+ mStringType = STRING_TYPE_MAGNETIC_FIELD;
+ return true;
+ case TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ mStringType = STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED;
+ return true;
+ case TYPE_PICK_UP_GESTURE:
+ mStringType = STRING_TYPE_PICK_UP_GESTURE;
+ return true;
+ case TYPE_PRESSURE:
+ mStringType = STRING_TYPE_PRESSURE;
+ return true;
+ case TYPE_PROXIMITY:
+ mStringType = STRING_TYPE_PROXIMITY;
+ return true;
+ case TYPE_RELATIVE_HUMIDITY:
+ mStringType = STRING_TYPE_RELATIVE_HUMIDITY;
+ return true;
+ case TYPE_ROTATION_VECTOR:
+ mStringType = STRING_TYPE_ROTATION_VECTOR;
+ return true;
+ case TYPE_SIGNIFICANT_MOTION:
+ mStringType = STRING_TYPE_SIGNIFICANT_MOTION;
+ return true;
+ case TYPE_STEP_COUNTER:
+ mStringType = STRING_TYPE_STEP_COUNTER;
+ return true;
+ case TYPE_STEP_DETECTOR:
+ mStringType = STRING_TYPE_STEP_DETECTOR;
+ return true;
+ case TYPE_TILT_DETECTOR:
+ mStringType = SENSOR_STRING_TYPE_TILT_DETECTOR;
+ return true;
+ case TYPE_WAKE_GESTURE:
+ mStringType = STRING_TYPE_WAKE_GESTURE;
+ return true;
+ case TYPE_ORIENTATION:
+ mStringType = STRING_TYPE_ORIENTATION;
+ return true;
+ case TYPE_TEMPERATURE:
+ mStringType = STRING_TYPE_TEMPERATURE;
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 60ff32c..87ec06a 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -424,17 +424,6 @@
new Key<Rational>("android.control.aeCompensationStep", Rational.class);
/**
- * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</p>
- * <p>LIMITED or FULL devices will always list <code>true</code></p>
- * <p>This key is available on all devices.</p>
- *
- * @see CaptureRequest#CONTROL_AE_LOCK
- */
- @PublicKey
- public static final Key<Boolean> CONTROL_AE_LOCK_AVAILABLE =
- new Key<Boolean>("android.control.aeLockAvailable", boolean.class);
-
- /**
* <p>List of auto-focus (AF) modes for {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} that are
* supported by this camera device.</p>
* <p>Not all the auto-focus modes may be supported by a
@@ -482,22 +471,6 @@
new Key<int[]>("android.control.availableEffects", int[].class);
/**
- * <p>List of control modes for {@link CaptureRequest#CONTROL_MODE android.control.mode} that are supported by this camera
- * device.</p>
- * <p>This list contains control modes that can be set for the camera device.
- * LEGACY mode devices will always support AUTO mode. LIMITED and FULL
- * devices will always support OFF, AUTO modes.</p>
- * <p><b>Range of valid values:</b><br>
- * Any value listed in {@link CaptureRequest#CONTROL_MODE android.control.mode}</p>
- * <p>This key is available on all devices.</p>
- *
- * @see CaptureRequest#CONTROL_MODE
- */
- @PublicKey
- public static final Key<int[]> CONTROL_AVAILABLE_MODES =
- new Key<int[]>("android.control.availableModes", int[].class);
-
- /**
* <p>List of scene modes for {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} that are supported by this camera
* device.</p>
* <p>This list contains scene modes that can be set for the camera device.
@@ -559,17 +532,6 @@
new Key<int[]>("android.control.awbAvailableModes", int[].class);
/**
- * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</p>
- * <p>LIMITED or FULL devices will always list <code>true</code></p>
- * <p>This key is available on all devices.</p>
- *
- * @see CaptureRequest#CONTROL_AWB_LOCK
- */
- @PublicKey
- public static final Key<Boolean> CONTROL_AWB_LOCK_AVAILABLE =
- new Key<Boolean>("android.control.awbLockAvailable", boolean.class);
-
- /**
* <p>List of the maximum number of regions that can be used for metering in
* auto-exposure (AE), auto-white balance (AWB), and auto-focus (AF);
* this corresponds to the the maximum number of elements in
@@ -676,6 +638,44 @@
new Key<android.hardware.camera2.params.HighSpeedVideoConfiguration[]>("android.control.availableHighSpeedVideoConfigurations", android.hardware.camera2.params.HighSpeedVideoConfiguration[].class);
/**
+ * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</p>
+ * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_LOCK
+ */
+ @PublicKey
+ public static final Key<Boolean> CONTROL_AE_LOCK_AVAILABLE =
+ new Key<Boolean>("android.control.aeLockAvailable", boolean.class);
+
+ /**
+ * <p>Whether the camera device supports {@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</p>
+ * <p>LIMITED or FULL devices will always list <code>true</code></p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_AWB_LOCK
+ */
+ @PublicKey
+ public static final Key<Boolean> CONTROL_AWB_LOCK_AVAILABLE =
+ new Key<Boolean>("android.control.awbLockAvailable", boolean.class);
+
+ /**
+ * <p>List of control modes for {@link CaptureRequest#CONTROL_MODE android.control.mode} that are supported by this camera
+ * device.</p>
+ * <p>This list contains control modes that can be set for the camera device.
+ * LEGACY mode devices will always support AUTO mode. LIMITED and FULL
+ * devices will always support OFF, AUTO modes.</p>
+ * <p><b>Range of valid values:</b><br>
+ * Any value listed in {@link CaptureRequest#CONTROL_MODE android.control.mode}</p>
+ * <p>This key is available on all devices.</p>
+ *
+ * @see CaptureRequest#CONTROL_MODE
+ */
+ @PublicKey
+ public static final Key<int[]> CONTROL_AVAILABLE_MODES =
+ new Key<int[]>("android.control.availableModes", int[].class);
+
+ /**
* <p>List of edge enhancement modes for {@link CaptureRequest#EDGE_MODE android.edge.mode} that are supported by this camera
* device.</p>
* <p>Full-capability camera devices must always support OFF; all devices will list FAST.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ffe30d4..7f901c8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -380,8 +380,8 @@
* <li>{@link CaptureRequest#TONEMAP_CURVE android.tonemap.curve}</li>
* <li>{@link CaptureRequest#TONEMAP_MODE android.tonemap.mode}</li>
* <li>{@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}</li>
- * <li>{@link CaptureRequest#TONEMAP_GAMMA android.tonemap.gamma}</li>
- * <li>{@link CaptureRequest#TONEMAP_PRESET_CURVE android.tonemap.presetCurve}</li>
+ * <li>android.tonemap.gamma</li>
+ * <li>android.tonemap.presetCurve</li>
* </ul>
* </li>
* <li>
@@ -416,10 +416,8 @@
* @see CaptureRequest#SHADING_MODE
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
* @see CaptureRequest#TONEMAP_CURVE
- * @see CaptureRequest#TONEMAP_GAMMA
* @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
* @see CaptureRequest#TONEMAP_MODE
- * @see CaptureRequest#TONEMAP_PRESET_CURVE
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2;
@@ -2113,26 +2111,22 @@
public static final int TONEMAP_MODE_HIGH_QUALITY = 2;
/**
- * <p>Use the gamma value specified in {@link CaptureRequest#TONEMAP_GAMMA android.tonemap.gamma} to peform
+ * <p>Use the gamma value specified in android.tonemap.gamma to peform
* tonemapping.</p>
* <p>All color enhancement and tonemapping must be disabled, except
- * for applying the tonemapping curve specified by {@link CaptureRequest#TONEMAP_GAMMA android.tonemap.gamma}.</p>
+ * for applying the tonemapping curve specified by android.tonemap.gamma.</p>
* <p>Must not slow down frame rate relative to raw sensor output.</p>
- *
- * @see CaptureRequest#TONEMAP_GAMMA
* @see CaptureRequest#TONEMAP_MODE
*/
public static final int TONEMAP_MODE_GAMMA_VALUE = 3;
/**
* <p>Use the preset tonemapping curve specified in
- * {@link CaptureRequest#TONEMAP_PRESET_CURVE android.tonemap.presetCurve} to peform tonemapping.</p>
+ * android.tonemap.presetCurve to peform tonemapping.</p>
* <p>All color enhancement and tonemapping must be disabled, except
* for applying the tonemapping curve specified by
- * {@link CaptureRequest#TONEMAP_PRESET_CURVE android.tonemap.presetCurve}.</p>
+ * android.tonemap.presetCurve.</p>
* <p>Must not slow down frame rate relative to raw sensor output.</p>
- *
- * @see CaptureRequest#TONEMAP_PRESET_CURVE
* @see CaptureRequest#TONEMAP_MODE
*/
public static final int TONEMAP_MODE_PRESET_CURVE = 4;
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index a0a0716..615b2c8 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -269,21 +269,23 @@
throw new IllegalStateException("Illegal intermediate texture with dimension of 0");
}
- // Letterbox or pillerbox output dimensions into intermediate dimensions.
+ // Letterbox or pillar-box output dimensions into intermediate dimensions.
RectF intermediate = new RectF(/*left*/0, /*top*/0, /*right*/texWidth, /*bottom*/texHeight);
RectF output = new RectF(/*left*/0, /*top*/0, /*right*/width, /*bottom*/height);
android.graphics.Matrix boxingXform = new android.graphics.Matrix();
boxingXform.setRectToRect(output, intermediate, android.graphics.Matrix.ScaleToFit.CENTER);
boxingXform.mapRect(output);
- // Find scaling factor from pillerboxed/letterboxed output dimensions to intermediate
+ // Find scaling factor from pillar-boxed/letter-boxed output dimensions to intermediate
// buffer dimensions.
float scaleX = intermediate.width() / output.width();
float scaleY = intermediate.height() / output.height();
- // Scale opposite dimension in clip coordinates so output is letterboxed/pillerboxed into
- // the intermediate dimensions (rather than vice-versa).
- Matrix.scaleM(mMVPMatrix, /*offset*/0, /*x*/scaleY, /*y*/scaleX, /*z*/1);
+ // Intermediate texture is implicitly scaled to 'fill' the output dimensions in clip space
+ // coordinates in the shader. To avoid stretching, we need to scale the larger dimension
+ // of the intermediate buffer so that the output buffer is actually letter-boxed
+ // or pillar-boxed into the intermediate buffer after clipping.
+ Matrix.scaleM(mMVPMatrix, /*offset*/0, /*x*/scaleX, /*y*/scaleY, /*z*/1);
if (DEBUG) {
Log.d(TAG, "Scaling factors (S_x = " + scaleX + ",S_y = " + scaleY + ") used for " +
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 0051ef5..d9f9c1e 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -17,10 +17,10 @@
package android.hardware.display;
import android.content.Context;
+import android.content.res.Configuration;
import android.hardware.display.DisplayManager.DisplayListener;
import android.media.projection.MediaProjection;
import android.media.projection.IMediaProjection;
-import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -196,11 +196,11 @@
* Gets information about a logical display without applying any compatibility metrics.
*
* @param displayId The logical display id.
- * @param IBinder the activity token for this display.
+ * @param configuration the configuration.
* @return The display object, or null if there is no display with the given id.
*/
- public Display getRealDisplay(int displayId, IBinder token) {
- return getCompatibleDisplay(displayId, new DisplayAdjustments(token));
+ public Display getRealDisplay(int displayId, Configuration configuration) {
+ return getCompatibleDisplay(displayId, new DisplayAdjustments(configuration));
}
public void registerDisplayListener(DisplayListener listener, Handler handler) {
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2eb42a7..481fc2f 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -19,6 +19,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.annotation.DrawableRes;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
@@ -708,6 +709,7 @@
mRootView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mWindow.setContentView(mRootView);
+ mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
if (Settings.Global.getInt(getContentResolver(),
Settings.Global.FANCY_IME_ANIMATIONS, 0) != 0) {
@@ -1177,7 +1179,7 @@
return isExtractViewShown() ? View.GONE : View.INVISIBLE;
}
- public void showStatusIcon(int iconResId) {
+ public void showStatusIcon(@DrawableRes int iconResId) {
mStatusIcon = iconResId;
mImm.showStatusIcon(mToken, getPackageName(), iconResId);
}
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 4fe54c0..45f1889 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -18,6 +18,7 @@
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -519,7 +520,8 @@
* @param width sets width of keyboard
* @param height sets height of keyboard
*/
- public Keyboard(Context context, int xmlLayoutResId, int modeId, int width, int height) {
+ public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width,
+ int height) {
mDisplayWidth = width;
mDisplayHeight = height;
@@ -540,7 +542,7 @@
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
* @param modeId keyboard mode identifier
*/
- public Keyboard(Context context, int xmlLayoutResId, int modeId) {
+ public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
mDisplayWidth = dm.widthPixels;
mDisplayHeight = dm.heightPixels;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1a51808..808be21 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2371,6 +2371,10 @@
* The lookup key for a {@link Network} object included with the intent after
* successfully finding a network for the applications request. Retrieve it with
* {@link android.content.Intent#getParcelableExtra(String)}.
+ * <p>
+ * Note that if you intend to invoke (@link #setProcessDefaultNetwork(Network)) or
+ * {@link Network#openConnection(java.net.URL)} then you must get a
+ * ConnectivityManager instance before doing so.
*/
public static final String EXTRA_NETWORK = "android.net.extra.NETWORK";
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index a3cad77..2c90909 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -21,8 +21,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
-import org.apache.http.client.HttpClient;
-
import java.net.InetSocketAddress;
import java.net.URLConnection;
import java.util.List;
@@ -31,8 +29,9 @@
/**
* Describes a proxy configuration.
*
- * Proxy configurations are already integrated within the Apache HTTP stack.
- * So {@link URLConnection} and {@link HttpClient} will use them automatically.
+ * Proxy configurations are already integrated within the {@code java.net} and
+ * Apache HTTP stack. So {@link URLConnection} and Apache's {@code HttpClient} will use
+ * them automatically.
*
* Other HTTP stacks will need to obtain the proxy info from
* {@link Proxy#PROXY_CHANGE_ACTION} broadcast as the extra {@link Proxy#EXTRA_PROXY_INFO}.
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
deleted file mode 100644
index a262076..0000000
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * 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.net.http;
-
-import com.android.internal.http.HttpDateTime;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.PlainSocketFactory;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.RequestWrapper;
-import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.BasicHttpProcessor;
-import org.apache.http.protocol.HttpContext;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.net.SSLCertificateSocketFactory;
-import android.net.SSLSessionCache;
-import android.os.Looper;
-import android.util.Base64;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-/**
- * Implementation of the Apache {@link DefaultHttpClient} that is configured with
- * reasonable default settings and registered schemes for Android.
- * Don't create this directly, use the {@link #newInstance} factory method.
- *
- * <p>This client processes cookies but does not retain them by default.
- * To retain cookies, simply add a cookie store to the HttpContext:</p>
- *
- * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead.
- * The Apache HTTP client is no longer maintained and may be removed in a future
- * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
- * for further details.
- */
-@Deprecated
-public final class AndroidHttpClient implements HttpClient {
-
- // Gzip of data shorter than this probably won't be worthwhile
- public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
-
- // Default connection and socket timeout of 60 seconds. Tweak to taste.
- private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000;
-
- private static final String TAG = "AndroidHttpClient";
-
- private static String[] textContentTypes = new String[] {
- "text/",
- "application/xml",
- "application/json"
- };
-
- /** Interceptor throws an exception if the executing thread is blocked */
- private static final HttpRequestInterceptor sThreadCheckInterceptor =
- new HttpRequestInterceptor() {
- public void process(HttpRequest request, HttpContext context) {
- // Prevent the HttpRequest from being sent on the main thread
- if (Looper.myLooper() != null && Looper.myLooper() == Looper.getMainLooper() ) {
- throw new RuntimeException("This thread forbids HTTP requests");
- }
- }
- };
-
- /**
- * Create a new HttpClient with reasonable defaults (which you can update).
- *
- * @param userAgent to report in your HTTP requests
- * @param context to use for caching SSL sessions (may be null for no caching)
- * @return AndroidHttpClient for you to use for all your requests.
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead. See
- * {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd
- * like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)}
- * with {@code field} set to {@code User-Agent}.
- */
- @Deprecated
- public static AndroidHttpClient newInstance(String userAgent, Context context) {
- HttpParams params = new BasicHttpParams();
-
- // Turn off stale checking. Our connections break all the time anyway,
- // and it's not worth it to pay the penalty of checking every time.
- HttpConnectionParams.setStaleCheckingEnabled(params, false);
-
- HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT);
- HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT);
- HttpConnectionParams.setSocketBufferSize(params, 8192);
-
- // Don't handle redirects -- return them to the caller. Our code
- // often wants to re-POST after a redirect, which we must do ourselves.
- HttpClientParams.setRedirecting(params, false);
-
- // Use a session cache for SSL sockets
- SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context);
-
- // Set the specified user agent and register standard protocols.
- HttpProtocolParams.setUserAgent(params, userAgent);
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(new Scheme("http",
- PlainSocketFactory.getSocketFactory(), 80));
- schemeRegistry.register(new Scheme("https",
- SSLCertificateSocketFactory.getHttpSocketFactory(
- SOCKET_OPERATION_TIMEOUT, sessionCache), 443));
-
- ClientConnectionManager manager =
- new ThreadSafeClientConnManager(params, schemeRegistry);
-
- // We use a factory method to modify superclass initialization
- // parameters without the funny call-a-static-method dance.
- return new AndroidHttpClient(manager, params);
- }
-
- /**
- * Create a new HttpClient with reasonable defaults (which you can update).
- * @param userAgent to report in your HTTP requests.
- * @return AndroidHttpClient for you to use for all your requests.
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead. See
- * {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd
- * like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)}
- * with {@code field} set to {@code User-Agent}.
- */
- @Deprecated
- public static AndroidHttpClient newInstance(String userAgent) {
- return newInstance(userAgent, null /* session cache */);
- }
-
- private final HttpClient delegate;
-
- private RuntimeException mLeakedException = new IllegalStateException(
- "AndroidHttpClient created and never closed");
-
- private AndroidHttpClient(ClientConnectionManager ccm, HttpParams params) {
- this.delegate = new DefaultHttpClient(ccm, params) {
- @Override
- protected BasicHttpProcessor createHttpProcessor() {
- // Add interceptor to prevent making requests from main thread.
- BasicHttpProcessor processor = super.createHttpProcessor();
- processor.addRequestInterceptor(sThreadCheckInterceptor);
- processor.addRequestInterceptor(new CurlLogger());
-
- return processor;
- }
-
- @Override
- protected HttpContext createHttpContext() {
- // Same as DefaultHttpClient.createHttpContext() minus the
- // cookie store.
- HttpContext context = new BasicHttpContext();
- context.setAttribute(
- ClientContext.AUTHSCHEME_REGISTRY,
- getAuthSchemes());
- context.setAttribute(
- ClientContext.COOKIESPEC_REGISTRY,
- getCookieSpecs());
- context.setAttribute(
- ClientContext.CREDS_PROVIDER,
- getCredentialsProvider());
- return context;
- }
- };
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- if (mLeakedException != null) {
- Log.e(TAG, "Leak found", mLeakedException);
- mLeakedException = null;
- }
- }
-
- /**
- * Modifies a request to indicate to the server that we would like a
- * gzipped response. (Uses the "Accept-Encoding" HTTP header.)
- * @param request the request to modify
- * @see #getUngzippedContent
- */
- public static void modifyRequestToAcceptGzipResponse(HttpRequest request) {
- request.addHeader("Accept-Encoding", "gzip");
- }
-
- /**
- * Gets the input stream from a response entity. If the entity is gzipped
- * then this will get a stream over the uncompressed data.
- *
- * @param entity the entity whose content should be read
- * @return the input stream to read from
- * @throws IOException
- */
- public static InputStream getUngzippedContent(HttpEntity entity)
- throws IOException {
- InputStream responseStream = entity.getContent();
- if (responseStream == null) return responseStream;
- Header header = entity.getContentEncoding();
- if (header == null) return responseStream;
- String contentEncoding = header.getValue();
- if (contentEncoding == null) return responseStream;
- if (contentEncoding.contains("gzip")) responseStream
- = new GZIPInputStream(responseStream);
- return responseStream;
- }
-
- /**
- * Release resources associated with this client. You must call this,
- * or significant resources (sockets and memory) may be leaked.
- */
- public void close() {
- if (mLeakedException != null) {
- getConnectionManager().shutdown();
- mLeakedException = null;
- }
- }
-
- public HttpParams getParams() {
- return delegate.getParams();
- }
-
- public ClientConnectionManager getConnectionManager() {
- return delegate.getConnectionManager();
- }
-
- public HttpResponse execute(HttpUriRequest request) throws IOException {
- return delegate.execute(request);
- }
-
- public HttpResponse execute(HttpUriRequest request, HttpContext context)
- throws IOException {
- return delegate.execute(request, context);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request)
- throws IOException {
- return delegate.execute(target, request);
- }
-
- public HttpResponse execute(HttpHost target, HttpRequest request,
- HttpContext context) throws IOException {
- return delegate.execute(target, request, context);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler);
- }
-
- public <T> T execute(HttpUriRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(request, responseHandler, context);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler) throws IOException,
- ClientProtocolException {
- return delegate.execute(target, request, responseHandler);
- }
-
- public <T> T execute(HttpHost target, HttpRequest request,
- ResponseHandler<? extends T> responseHandler, HttpContext context)
- throws IOException, ClientProtocolException {
- return delegate.execute(target, request, responseHandler, context);
- }
-
- /**
- * Compress data to send to server.
- * Creates a Http Entity holding the gzipped data.
- * The data will not be compressed if it is too short.
- * @param data The bytes to compress
- * @return Entity holding the data
- */
- public static AbstractHttpEntity getCompressedEntity(byte data[], ContentResolver resolver)
- throws IOException {
- AbstractHttpEntity entity;
- if (data.length < getMinGzipSize(resolver)) {
- entity = new ByteArrayEntity(data);
- } else {
- ByteArrayOutputStream arr = new ByteArrayOutputStream();
- OutputStream zipper = new GZIPOutputStream(arr);
- zipper.write(data);
- zipper.close();
- entity = new ByteArrayEntity(arr.toByteArray());
- entity.setContentEncoding("gzip");
- }
- return entity;
- }
-
- /**
- * Retrieves the minimum size for compressing data.
- * Shorter data will not be compressed.
- */
- public static long getMinGzipSize(ContentResolver resolver) {
- return DEFAULT_SYNC_MIN_GZIP_BYTES; // For now, this is just a constant.
- }
-
- /* cURL logging support. */
-
- /**
- * Logging tag and level.
- */
- private static class LoggingConfiguration {
-
- private final String tag;
- private final int level;
-
- private LoggingConfiguration(String tag, int level) {
- this.tag = tag;
- this.level = level;
- }
-
- /**
- * Returns true if logging is turned on for this configuration.
- */
- private boolean isLoggable() {
- return Log.isLoggable(tag, level);
- }
-
- /**
- * Prints a message using this configuration.
- */
- private void println(String message) {
- Log.println(level, tag, message);
- }
- }
-
- /** cURL logging configuration. */
- private volatile LoggingConfiguration curlConfiguration;
-
- /**
- * Enables cURL request logging for this client.
- *
- * @param name to log messages with
- * @param level at which to log messages (see {@link android.util.Log})
- */
- public void enableCurlLogging(String name, int level) {
- if (name == null) {
- throw new NullPointerException("name");
- }
- if (level < Log.VERBOSE || level > Log.ASSERT) {
- throw new IllegalArgumentException("Level is out of range ["
- + Log.VERBOSE + ".." + Log.ASSERT + "]");
- }
-
- curlConfiguration = new LoggingConfiguration(name, level);
- }
-
- /**
- * Disables cURL logging for this client.
- */
- public void disableCurlLogging() {
- curlConfiguration = null;
- }
-
- /**
- * Logs cURL commands equivalent to requests.
- */
- private class CurlLogger implements HttpRequestInterceptor {
- public void process(HttpRequest request, HttpContext context)
- throws HttpException, IOException {
- LoggingConfiguration configuration = curlConfiguration;
- if (configuration != null
- && configuration.isLoggable()
- && request instanceof HttpUriRequest) {
- // Never print auth token -- we used to check ro.secure=0 to
- // enable that, but can't do that in unbundled code.
- configuration.println(toCurl((HttpUriRequest) request, false));
- }
- }
- }
-
- /**
- * Generates a cURL command equivalent to the given request.
- */
- private static String toCurl(HttpUriRequest request, boolean logAuthToken) throws IOException {
- StringBuilder builder = new StringBuilder();
-
- builder.append("curl ");
-
- // add in the method
- builder.append("-X ");
- builder.append(request.getMethod());
- builder.append(" ");
-
- for (Header header: request.getAllHeaders()) {
- if (!logAuthToken
- && (header.getName().equals("Authorization") ||
- header.getName().equals("Cookie"))) {
- continue;
- }
- builder.append("--header \"");
- builder.append(header.toString().trim());
- builder.append("\" ");
- }
-
- URI uri = request.getURI();
-
- // If this is a wrapped request, use the URI from the original
- // request instead. getURI() on the wrapper seems to return a
- // relative URI. We want an absolute URI.
- if (request instanceof RequestWrapper) {
- HttpRequest original = ((RequestWrapper) request).getOriginal();
- if (original instanceof HttpUriRequest) {
- uri = ((HttpUriRequest) original).getURI();
- }
- }
-
- builder.append("\"");
- builder.append(uri);
- builder.append("\"");
-
- if (request instanceof HttpEntityEnclosingRequest) {
- HttpEntityEnclosingRequest entityRequest =
- (HttpEntityEnclosingRequest) request;
- HttpEntity entity = entityRequest.getEntity();
- if (entity != null && entity.isRepeatable()) {
- if (entity.getContentLength() < 1024) {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- entity.writeTo(stream);
-
- if (isBinaryContent(request)) {
- String base64 = Base64.encodeToString(stream.toByteArray(), Base64.NO_WRAP);
- builder.insert(0, "echo '" + base64 + "' | base64 -d > /tmp/$$.bin; ");
- builder.append(" --data-binary @/tmp/$$.bin");
- } else {
- String entityString = stream.toString();
- builder.append(" --data-ascii \"")
- .append(entityString)
- .append("\"");
- }
- } else {
- builder.append(" [TOO MUCH DATA TO INCLUDE]");
- }
- }
- }
-
- return builder.toString();
- }
-
- private static boolean isBinaryContent(HttpUriRequest request) {
- Header[] headers;
- headers = request.getHeaders(Headers.CONTENT_ENCODING);
- if (headers != null) {
- for (Header header : headers) {
- if ("gzip".equalsIgnoreCase(header.getValue())) {
- return true;
- }
- }
- }
-
- headers = request.getHeaders(Headers.CONTENT_TYPE);
- if (headers != null) {
- for (Header header : headers) {
- for (String contentType : textContentTypes) {
- if (header.getValue().startsWith(contentType)) {
- return false;
- }
- }
- }
- }
- return true;
- }
-
- /**
- * Returns the date of the given HTTP date string. This method can identify
- * and parse the date formats emitted by common HTTP servers, such as
- * <a href="http://www.ietf.org/rfc/rfc0822.txt">RFC 822</a>,
- * <a href="http://www.ietf.org/rfc/rfc0850.txt">RFC 850</a>,
- * <a href="http://www.ietf.org/rfc/rfc1036.txt">RFC 1036</a>,
- * <a href="http://www.ietf.org/rfc/rfc1123.txt">RFC 1123</a> and
- * <a href="http://www.opengroup.org/onlinepubs/007908799/xsh/asctime.html">ANSI
- * C's asctime()</a>.
- *
- * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
- * @throws IllegalArgumentException if {@code dateString} is not a date or
- * of an unsupported format.
- */
- public static long parseDate(String dateString) {
- return HttpDateTime.parse(dateString);
- }
-}
diff --git a/core/java/android/net/http/AndroidHttpClientConnection.java b/core/java/android/net/http/AndroidHttpClientConnection.java
deleted file mode 100644
index 6d48fce..0000000
--- a/core/java/android/net/http/AndroidHttpClientConnection.java
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import org.apache.http.HttpConnection;
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpConnectionMetrics;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpInetConnection;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.NoHttpResponseException;
-import org.apache.http.StatusLine;
-import org.apache.http.entity.BasicHttpEntity;
-import org.apache.http.entity.ContentLengthStrategy;
-import org.apache.http.impl.HttpConnectionMetricsImpl;
-import org.apache.http.impl.entity.EntitySerializer;
-import org.apache.http.impl.entity.StrictContentLengthStrategy;
-import org.apache.http.impl.io.ChunkedInputStream;
-import org.apache.http.impl.io.ContentLengthInputStream;
-import org.apache.http.impl.io.HttpRequestWriter;
-import org.apache.http.impl.io.IdentityInputStream;
-import org.apache.http.impl.io.SocketInputBuffer;
-import org.apache.http.impl.io.SocketOutputBuffer;
-import org.apache.http.io.HttpMessageWriter;
-import org.apache.http.io.SessionInputBuffer;
-import org.apache.http.io.SessionOutputBuffer;
-import org.apache.http.message.BasicLineParser;
-import org.apache.http.message.ParserCursor;
-import org.apache.http.params.CoreConnectionPNames;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.ParseException;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * A alternate class for (@link DefaultHttpClientConnection).
- * It has better performance than DefaultHttpClientConnection
- *
- * {@hide}
- */
-public class AndroidHttpClientConnection
- implements HttpInetConnection, HttpConnection {
-
- private SessionInputBuffer inbuffer = null;
- private SessionOutputBuffer outbuffer = null;
- private int maxHeaderCount;
- // store CoreConnectionPNames.MAX_LINE_LENGTH for performance
- private int maxLineLength;
-
- private final EntitySerializer entityserializer;
-
- private HttpMessageWriter requestWriter = null;
- private HttpConnectionMetricsImpl metrics = null;
- private volatile boolean open;
- private Socket socket = null;
-
- public AndroidHttpClientConnection() {
- this.entityserializer = new EntitySerializer(
- new StrictContentLengthStrategy());
- }
-
- /**
- * Bind socket and set HttpParams to AndroidHttpClientConnection
- * @param socket outgoing socket
- * @param params HttpParams
- * @throws IOException
- */
- public void bind(
- final Socket socket,
- final HttpParams params) throws IOException {
- if (socket == null) {
- throw new IllegalArgumentException("Socket may not be null");
- }
- if (params == null) {
- throw new IllegalArgumentException("HTTP parameters may not be null");
- }
- assertNotOpen();
- socket.setTcpNoDelay(HttpConnectionParams.getTcpNoDelay(params));
- socket.setSoTimeout(HttpConnectionParams.getSoTimeout(params));
-
- int linger = HttpConnectionParams.getLinger(params);
- if (linger >= 0) {
- socket.setSoLinger(linger > 0, linger);
- }
- this.socket = socket;
-
- int buffersize = HttpConnectionParams.getSocketBufferSize(params);
- this.inbuffer = new SocketInputBuffer(socket, buffersize, params);
- this.outbuffer = new SocketOutputBuffer(socket, buffersize, params);
-
- maxHeaderCount = params.getIntParameter(
- CoreConnectionPNames.MAX_HEADER_COUNT, -1);
- maxLineLength = params.getIntParameter(
- CoreConnectionPNames.MAX_LINE_LENGTH, -1);
-
- this.requestWriter = new HttpRequestWriter(outbuffer, null, params);
-
- this.metrics = new HttpConnectionMetricsImpl(
- inbuffer.getMetrics(),
- outbuffer.getMetrics());
-
- this.open = true;
- }
-
- @Override
- public String toString() {
- StringBuilder buffer = new StringBuilder();
- buffer.append(getClass().getSimpleName()).append("[");
- if (isOpen()) {
- buffer.append(getRemotePort());
- } else {
- buffer.append("closed");
- }
- buffer.append("]");
- return buffer.toString();
- }
-
-
- private void assertNotOpen() {
- if (this.open) {
- throw new IllegalStateException("Connection is already open");
- }
- }
-
- private void assertOpen() {
- if (!this.open) {
- throw new IllegalStateException("Connection is not open");
- }
- }
-
- public boolean isOpen() {
- // to make this method useful, we want to check if the socket is connected
- return (this.open && this.socket != null && this.socket.isConnected());
- }
-
- public InetAddress getLocalAddress() {
- if (this.socket != null) {
- return this.socket.getLocalAddress();
- } else {
- return null;
- }
- }
-
- public int getLocalPort() {
- if (this.socket != null) {
- return this.socket.getLocalPort();
- } else {
- return -1;
- }
- }
-
- public InetAddress getRemoteAddress() {
- if (this.socket != null) {
- return this.socket.getInetAddress();
- } else {
- return null;
- }
- }
-
- public int getRemotePort() {
- if (this.socket != null) {
- return this.socket.getPort();
- } else {
- return -1;
- }
- }
-
- public void setSocketTimeout(int timeout) {
- assertOpen();
- if (this.socket != null) {
- try {
- this.socket.setSoTimeout(timeout);
- } catch (SocketException ignore) {
- // It is not quite clear from the original documentation if there are any
- // other legitimate cases for a socket exception to be thrown when setting
- // SO_TIMEOUT besides the socket being already closed
- }
- }
- }
-
- public int getSocketTimeout() {
- if (this.socket != null) {
- try {
- return this.socket.getSoTimeout();
- } catch (SocketException ignore) {
- return -1;
- }
- } else {
- return -1;
- }
- }
-
- public void shutdown() throws IOException {
- this.open = false;
- Socket tmpsocket = this.socket;
- if (tmpsocket != null) {
- tmpsocket.close();
- }
- }
-
- public void close() throws IOException {
- if (!this.open) {
- return;
- }
- this.open = false;
- doFlush();
- try {
- try {
- this.socket.shutdownOutput();
- } catch (IOException ignore) {
- }
- try {
- this.socket.shutdownInput();
- } catch (IOException ignore) {
- }
- } catch (UnsupportedOperationException ignore) {
- // if one isn't supported, the other one isn't either
- }
- this.socket.close();
- }
-
- /**
- * Sends the request line and all headers over the connection.
- * @param request the request whose headers to send.
- * @throws HttpException
- * @throws IOException
- */
- public void sendRequestHeader(final HttpRequest request)
- throws HttpException, IOException {
- if (request == null) {
- throw new IllegalArgumentException("HTTP request may not be null");
- }
- assertOpen();
- this.requestWriter.write(request);
- this.metrics.incrementRequestCount();
- }
-
- /**
- * Sends the request entity over the connection.
- * @param request the request whose entity to send.
- * @throws HttpException
- * @throws IOException
- */
- public void sendRequestEntity(final HttpEntityEnclosingRequest request)
- throws HttpException, IOException {
- if (request == null) {
- throw new IllegalArgumentException("HTTP request may not be null");
- }
- assertOpen();
- if (request.getEntity() == null) {
- return;
- }
- this.entityserializer.serialize(
- this.outbuffer,
- request,
- request.getEntity());
- }
-
- protected void doFlush() throws IOException {
- this.outbuffer.flush();
- }
-
- public void flush() throws IOException {
- assertOpen();
- doFlush();
- }
-
- /**
- * Parses the response headers and adds them to the
- * given {@code headers} object, and returns the response StatusLine
- * @param headers store parsed header to headers.
- * @throws IOException
- * @return StatusLine
- * @see HttpClientConnection#receiveResponseHeader()
- */
- public StatusLine parseResponseHeader(Headers headers)
- throws IOException, ParseException {
- assertOpen();
-
- CharArrayBuffer current = new CharArrayBuffer(64);
-
- if (inbuffer.readLine(current) == -1) {
- throw new NoHttpResponseException("The target server failed to respond");
- }
-
- // Create the status line from the status string
- StatusLine statusline = BasicLineParser.DEFAULT.parseStatusLine(
- current, new ParserCursor(0, current.length()));
-
- if (HttpLog.LOGV) HttpLog.v("read: " + statusline);
- int statusCode = statusline.getStatusCode();
-
- // Parse header body
- CharArrayBuffer previous = null;
- int headerNumber = 0;
- while(true) {
- if (current == null) {
- current = new CharArrayBuffer(64);
- } else {
- // This must be he buffer used to parse the status
- current.clear();
- }
- int l = inbuffer.readLine(current);
- if (l == -1 || current.length() < 1) {
- break;
- }
- // Parse the header name and value
- // Check for folded headers first
- // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
- // discussion on folded headers
- char first = current.charAt(0);
- if ((first == ' ' || first == '\t') && previous != null) {
- // we have continuation folded header
- // so append value
- int start = 0;
- int length = current.length();
- while (start < length) {
- char ch = current.charAt(start);
- if (ch != ' ' && ch != '\t') {
- break;
- }
- start++;
- }
- if (maxLineLength > 0 &&
- previous.length() + 1 + current.length() - start >
- maxLineLength) {
- throw new IOException("Maximum line length limit exceeded");
- }
- previous.append(' ');
- previous.append(current, start, current.length() - start);
- } else {
- if (previous != null) {
- headers.parseHeader(previous);
- }
- headerNumber++;
- previous = current;
- current = null;
- }
- if (maxHeaderCount > 0 && headerNumber >= maxHeaderCount) {
- throw new IOException("Maximum header count exceeded");
- }
- }
-
- if (previous != null) {
- headers.parseHeader(previous);
- }
-
- if (statusCode >= 200) {
- this.metrics.incrementResponseCount();
- }
- return statusline;
- }
-
- /**
- * Return the next response entity.
- * @param headers contains values for parsing entity
- * @see HttpClientConnection#receiveResponseEntity(HttpResponse response)
- */
- public HttpEntity receiveResponseEntity(final Headers headers) {
- assertOpen();
- BasicHttpEntity entity = new BasicHttpEntity();
-
- long len = determineLength(headers);
- if (len == ContentLengthStrategy.CHUNKED) {
- entity.setChunked(true);
- entity.setContentLength(-1);
- entity.setContent(new ChunkedInputStream(inbuffer));
- } else if (len == ContentLengthStrategy.IDENTITY) {
- entity.setChunked(false);
- entity.setContentLength(-1);
- entity.setContent(new IdentityInputStream(inbuffer));
- } else {
- entity.setChunked(false);
- entity.setContentLength(len);
- entity.setContent(new ContentLengthInputStream(inbuffer, len));
- }
-
- String contentTypeHeader = headers.getContentType();
- if (contentTypeHeader != null) {
- entity.setContentType(contentTypeHeader);
- }
- String contentEncodingHeader = headers.getContentEncoding();
- if (contentEncodingHeader != null) {
- entity.setContentEncoding(contentEncodingHeader);
- }
-
- return entity;
- }
-
- private long determineLength(final Headers headers) {
- long transferEncoding = headers.getTransferEncoding();
- // We use Transfer-Encoding if present and ignore Content-Length.
- // RFC2616, 4.4 item number 3
- if (transferEncoding < Headers.NO_TRANSFER_ENCODING) {
- return transferEncoding;
- } else {
- long contentlen = headers.getContentLength();
- if (contentlen > Headers.NO_CONTENT_LENGTH) {
- return contentlen;
- } else {
- return ContentLengthStrategy.IDENTITY;
- }
- }
- }
-
- /**
- * Checks whether this connection has gone down.
- * Network connections may get closed during some time of inactivity
- * for several reasons. The next time a read is attempted on such a
- * connection it will throw an IOException.
- * This method tries to alleviate this inconvenience by trying to
- * find out if a connection is still usable. Implementations may do
- * that by attempting a read with a very small timeout. Thus this
- * method may block for a small amount of time before returning a result.
- * It is therefore an <i>expensive</i> operation.
- *
- * @return <code>true</code> if attempts to use this connection are
- * likely to succeed, or <code>false</code> if they are likely
- * to fail and this connection should be closed
- */
- public boolean isStale() {
- assertOpen();
- try {
- this.inbuffer.isDataAvailable(1);
- return false;
- } catch (IOException ex) {
- return true;
- }
- }
-
- /**
- * Returns a collection of connection metrcis
- * @return HttpConnectionMetrics
- */
- public HttpConnectionMetrics getMetrics() {
- return this.metrics;
- }
-}
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
deleted file mode 100644
index bf3fe02..0000000
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import com.android.org.conscrypt.SSLParametersImpl;
-import com.android.org.conscrypt.TrustManagerImpl;
-
-import android.util.Slog;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * Class responsible for all server certificate validation functionality
- *
- * {@hide}
- */
-public class CertificateChainValidator {
- private static final String TAG = "CertificateChainValidator";
-
- private static class NoPreloadHolder {
- /**
- * The singleton instance of the certificate chain validator.
- */
- private static final CertificateChainValidator sInstance = new CertificateChainValidator();
-
- /**
- * The singleton instance of the hostname verifier.
- */
- private static final HostnameVerifier sVerifier = HttpsURLConnection
- .getDefaultHostnameVerifier();
- }
-
- private X509TrustManager mTrustManager;
-
- /**
- * @return The singleton instance of the certificates chain validator
- */
- public static CertificateChainValidator getInstance() {
- return NoPreloadHolder.sInstance;
- }
-
- /**
- * Creates a new certificate chain validator. This is a private constructor.
- * If you need a Certificate chain validator, call getInstance().
- */
- private CertificateChainValidator() {
- try {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
- tmf.init((KeyStore) null);
- for (TrustManager tm : tmf.getTrustManagers()) {
- if (tm instanceof X509TrustManager) {
- mTrustManager = (X509TrustManager) tm;
- }
- }
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
- } catch (KeyStoreException e) {
- throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
- }
-
- if (mTrustManager == null) {
- throw new RuntimeException(
- "None of the X.509 TrustManagers are X509TrustManager");
- }
- }
-
- /**
- * Performs the handshake and server certificates validation
- * Notice a new chain will be rebuilt by tracing the issuer and subject
- * before calling checkServerTrusted().
- * And if the last traced certificate is self issued and it is expired, it
- * will be dropped.
- * @param sslSocket The secure connection socket
- * @param domain The website domain
- * @return An SSL error object if there is an error and null otherwise
- */
- public SslError doHandshakeAndValidateServerCertificates(
- HttpsConnection connection, SSLSocket sslSocket, String domain)
- throws IOException {
- // get a valid SSLSession, close the socket if we fail
- SSLSession sslSession = sslSocket.getSession();
- if (!sslSession.isValid()) {
- closeSocketThrowException(sslSocket, "failed to perform SSL handshake");
- }
-
- // retrieve the chain of the server peer certificates
- Certificate[] peerCertificates =
- sslSocket.getSession().getPeerCertificates();
-
- if (peerCertificates == null || peerCertificates.length == 0) {
- closeSocketThrowException(
- sslSocket, "failed to retrieve peer certificates");
- } else {
- // update the SSL certificate associated with the connection
- if (connection != null) {
- if (peerCertificates[0] != null) {
- connection.setCertificate(
- new SslCertificate((X509Certificate)peerCertificates[0]));
- }
- }
- }
-
- return verifyServerDomainAndCertificates((X509Certificate[]) peerCertificates, domain, "RSA");
- }
-
- /**
- * Similar to doHandshakeAndValidateServerCertificates but exposed to JNI for use
- * by Chromium HTTPS stack to validate the cert chain.
- * @param certChain The bytes for certificates in ASN.1 DER encoded certificates format.
- * @param domain The full website hostname and domain
- * @param authType The authentication type for the cert chain
- * @return An SSL error object if there is an error and null otherwise
- */
- public static SslError verifyServerCertificates(
- byte[][] certChain, String domain, String authType)
- throws IOException {
-
- if (certChain == null || certChain.length == 0) {
- throw new IllegalArgumentException("bad certificate chain");
- }
-
- X509Certificate[] serverCertificates = new X509Certificate[certChain.length];
-
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- for (int i = 0; i < certChain.length; ++i) {
- serverCertificates[i] = (X509Certificate) cf.generateCertificate(
- new ByteArrayInputStream(certChain[i]));
- }
- } catch (CertificateException e) {
- throw new IOException("can't read certificate", e);
- }
-
- return verifyServerDomainAndCertificates(serverCertificates, domain, authType);
- }
-
- /**
- * Handles updates to credential storage.
- */
- public static void handleTrustStorageUpdate() {
- TrustManagerFactory tmf;
- try {
- tmf = TrustManagerFactory.getInstance("X.509");
- tmf.init((KeyStore) null);
- } catch (NoSuchAlgorithmException e) {
- Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
- return;
- } catch (KeyStoreException e) {
- Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
- return;
- }
-
- TrustManager[] tms = tmf.getTrustManagers();
- boolean sentUpdate = false;
- for (TrustManager tm : tms) {
- try {
- Method updateMethod = tm.getClass().getDeclaredMethod("handleTrustStorageUpdate");
- updateMethod.setAccessible(true);
- updateMethod.invoke(tm);
- sentUpdate = true;
- } catch (Exception e) {
- }
- }
- if (!sentUpdate) {
- Slog.w(TAG, "Didn't find a TrustManager to handle CA list update");
- }
- }
-
- /**
- * Common code of doHandshakeAndValidateServerCertificates and verifyServerCertificates.
- * Calls DomainNamevalidator to verify the domain, and TrustManager to verify the certs.
- * @param chain the cert chain in X509 cert format.
- * @param domain The full website hostname and domain
- * @param authType The authentication type for the cert chain
- * @return An SSL error object if there is an error and null otherwise
- */
- private static SslError verifyServerDomainAndCertificates(
- X509Certificate[] chain, String domain, String authType)
- throws IOException {
- // check if the first certificate in the chain is for this site
- X509Certificate currCertificate = chain[0];
- if (currCertificate == null) {
- throw new IllegalArgumentException("certificate for this site is null");
- }
-
- boolean valid = domain != null
- && !domain.isEmpty()
- && NoPreloadHolder.sVerifier.verify(domain,
- new DelegatingSSLSession.CertificateWrap(currCertificate));
- if (!valid) {
- if (HttpLog.LOGV) {
- HttpLog.v("certificate not for this host: " + domain);
- }
- return new SslError(SslError.SSL_IDMISMATCH, currCertificate);
- }
-
- try {
- X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultX509TrustManager();
- if (x509TrustManager instanceof TrustManagerImpl) {
- TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
- trustManager.checkServerTrusted(chain, authType, domain);
- } else {
- x509TrustManager.checkServerTrusted(chain, authType);
- }
- return null; // No errors.
- } catch (GeneralSecurityException e) {
- if (HttpLog.LOGV) {
- HttpLog.v("failed to validate the certificate chain, error: " +
- e.getMessage());
- }
- return new SslError(SslError.SSL_UNTRUSTED, currCertificate);
- }
- }
-
- /**
- * Returns the platform default {@link X509TrustManager}.
- */
- private X509TrustManager getTrustManager() {
- return mTrustManager;
- }
-
- private void closeSocketThrowException(
- SSLSocket socket, String errorMessage, String defaultErrorMessage)
- throws IOException {
- closeSocketThrowException(
- socket, errorMessage != null ? errorMessage : defaultErrorMessage);
- }
-
- private void closeSocketThrowException(SSLSocket socket,
- String errorMessage) throws IOException {
- if (HttpLog.LOGV) {
- HttpLog.v("validation error: " + errorMessage);
- }
-
- if (socket != null) {
- SSLSession session = socket.getSession();
- if (session != null) {
- session.invalidate();
- }
-
- socket.close();
- }
-
- throw new SSLHandshakeException(errorMessage);
- }
-}
diff --git a/core/java/android/net/http/Connection.java b/core/java/android/net/http/Connection.java
deleted file mode 100644
index 831bd0e..0000000
--- a/core/java/android/net/http/Connection.java
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * 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.net.http;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.LinkedList;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import org.apache.http.ConnectionReuseStrategy;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpVersion;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.protocol.ExecutionContext;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.BasicHttpContext;
-
-/**
- * {@hide}
- */
-abstract class Connection {
-
- /**
- * Allow a TCP connection 60 idle seconds before erroring out
- */
- static final int SOCKET_TIMEOUT = 60000;
-
- private static final int SEND = 0;
- private static final int READ = 1;
- private static final int DRAIN = 2;
- private static final int DONE = 3;
- private static final String[] states = {"SEND", "READ", "DRAIN", "DONE"};
-
- Context mContext;
-
- /** The low level connection */
- protected AndroidHttpClientConnection mHttpClientConnection = null;
-
- /**
- * The server SSL certificate associated with this connection
- * (null if the connection is not secure)
- * It would be nice to store the whole certificate chain, but
- * we want to keep things as light-weight as possible
- */
- protected SslCertificate mCertificate = null;
-
- /**
- * The host this connection is connected to. If using proxy,
- * this is set to the proxy address
- */
- HttpHost mHost;
-
- /** true if the connection can be reused for sending more requests */
- private boolean mCanPersist;
-
- /** context required by ConnectionReuseStrategy. */
- private HttpContext mHttpContext;
-
- /** set when cancelled */
- private static int STATE_NORMAL = 0;
- private static int STATE_CANCEL_REQUESTED = 1;
- private int mActive = STATE_NORMAL;
-
- /** The number of times to try to re-connect (if connect fails). */
- private final static int RETRY_REQUEST_LIMIT = 2;
-
- private static final int MIN_PIPE = 2;
- private static final int MAX_PIPE = 3;
-
- /**
- * Doesn't seem to exist anymore in the new HTTP client, so copied here.
- */
- private static final String HTTP_CONNECTION = "http.connection";
-
- RequestFeeder mRequestFeeder;
-
- /**
- * Buffer for feeding response blocks to webkit. One block per
- * connection reduces memory churn.
- */
- private byte[] mBuf;
-
- protected Connection(Context context, HttpHost host,
- RequestFeeder requestFeeder) {
- mContext = context;
- mHost = host;
- mRequestFeeder = requestFeeder;
-
- mCanPersist = false;
- mHttpContext = new BasicHttpContext(null);
- }
-
- HttpHost getHost() {
- return mHost;
- }
-
- /**
- * connection factory: returns an HTTP or HTTPS connection as
- * necessary
- */
- static Connection getConnection(
- Context context, HttpHost host, HttpHost proxy,
- RequestFeeder requestFeeder) {
-
- if (host.getSchemeName().equals("http")) {
- return new HttpConnection(context, host, requestFeeder);
- }
-
- // Otherwise, default to https
- return new HttpsConnection(context, host, proxy, requestFeeder);
- }
-
- /**
- * @return The server SSL certificate associated with this
- * connection (null if the connection is not secure)
- */
- /* package */ SslCertificate getCertificate() {
- return mCertificate;
- }
-
- /**
- * Close current network connection
- * Note: this runs in non-network thread
- */
- void cancel() {
- mActive = STATE_CANCEL_REQUESTED;
- closeConnection();
- if (HttpLog.LOGV) HttpLog.v(
- "Connection.cancel(): connection closed " + mHost);
- }
-
- /**
- * Process requests in queue
- * pipelines requests
- */
- void processRequests(Request firstRequest) {
- Request req = null;
- boolean empty;
- int error = EventHandler.OK;
- Exception exception = null;
-
- LinkedList<Request> pipe = new LinkedList<Request>();
-
- int minPipe = MIN_PIPE, maxPipe = MAX_PIPE;
- int state = SEND;
-
- while (state != DONE) {
- if (HttpLog.LOGV) HttpLog.v(
- states[state] + " pipe " + pipe.size());
-
- /* If a request was cancelled, give other cancel requests
- some time to go through so we don't uselessly restart
- connections */
- if (mActive == STATE_CANCEL_REQUESTED) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException x) { /* ignore */ }
- mActive = STATE_NORMAL;
- }
-
- switch (state) {
- case SEND: {
- if (pipe.size() == maxPipe) {
- state = READ;
- break;
- }
- /* get a request */
- if (firstRequest == null) {
- req = mRequestFeeder.getRequest(mHost);
- } else {
- req = firstRequest;
- firstRequest = null;
- }
- if (req == null) {
- state = DRAIN;
- break;
- }
- req.setConnection(this);
-
- /* Don't work on cancelled requests. */
- if (req.mCancelled) {
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests(): skipping cancelled request "
- + req);
- req.complete();
- break;
- }
-
- if (mHttpClientConnection == null ||
- !mHttpClientConnection.isOpen()) {
- /* If this call fails, the address is bad or
- the net is down. Punt for now.
-
- FIXME: blow out entire queue here on
- connection failure if net up? */
-
- if (!openHttpConnection(req)) {
- state = DONE;
- break;
- }
- }
-
- /* we have a connection, let the event handler
- * know of any associated certificate,
- * potentially none.
- */
- req.mEventHandler.certificate(mCertificate);
-
- try {
- /* FIXME: don't increment failure count if old
- connection? There should not be a penalty for
- attempting to reuse an old connection */
- req.sendRequest(mHttpClientConnection);
- } catch (HttpException e) {
- exception = e;
- error = EventHandler.ERROR;
- } catch (IOException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IllegalStateException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- }
- if (exception != null) {
- if (httpFailure(req, error, exception) &&
- !req.mCancelled) {
- /* retry request if not permanent failure
- or cancelled */
- pipe.addLast(req);
- }
- exception = null;
- state = clearPipe(pipe) ? DONE : SEND;
- minPipe = maxPipe = 1;
- break;
- }
-
- pipe.addLast(req);
- if (!mCanPersist) state = READ;
- break;
-
- }
- case DRAIN:
- case READ: {
- empty = !mRequestFeeder.haveRequest(mHost);
- int pipeSize = pipe.size();
- if (state != DRAIN && pipeSize < minPipe &&
- !empty && mCanPersist) {
- state = SEND;
- break;
- } else if (pipeSize == 0) {
- /* Done if no other work to do */
- state = empty ? DONE : SEND;
- break;
- }
-
- req = (Request)pipe.removeFirst();
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests() reading " + req);
-
- try {
- req.readResponse(mHttpClientConnection);
- } catch (ParseException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IOException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- } catch (IllegalStateException e) {
- exception = e;
- error = EventHandler.ERROR_IO;
- }
- if (exception != null) {
- if (httpFailure(req, error, exception) &&
- !req.mCancelled) {
- /* retry request if not permanent failure
- or cancelled */
- req.reset();
- pipe.addFirst(req);
- }
- exception = null;
- mCanPersist = false;
- }
- if (!mCanPersist) {
- if (HttpLog.LOGV) HttpLog.v(
- "processRequests(): no persist, closing " +
- mHost);
-
- closeConnection();
-
- mHttpContext.removeAttribute(HTTP_CONNECTION);
- clearPipe(pipe);
- minPipe = maxPipe = 1;
- state = SEND;
- }
- break;
- }
- }
- }
- }
-
- /**
- * After a send/receive failure, any pipelined requests must be
- * cleared back to the mRequest queue
- * @return true if mRequests is empty after pipe cleared
- */
- private boolean clearPipe(LinkedList<Request> pipe) {
- boolean empty = true;
- if (HttpLog.LOGV) HttpLog.v(
- "Connection.clearPipe(): clearing pipe " + pipe.size());
- synchronized (mRequestFeeder) {
- Request tReq;
- while (!pipe.isEmpty()) {
- tReq = (Request)pipe.removeLast();
- if (HttpLog.LOGV) HttpLog.v(
- "clearPipe() adding back " + mHost + " " + tReq);
- mRequestFeeder.requeueRequest(tReq);
- empty = false;
- }
- if (empty) empty = !mRequestFeeder.haveRequest(mHost);
- }
- return empty;
- }
-
- /**
- * @return true on success
- */
- private boolean openHttpConnection(Request req) {
-
- long now = SystemClock.uptimeMillis();
- int error = EventHandler.OK;
- Exception exception = null;
-
- try {
- // reset the certificate to null before opening a connection
- mCertificate = null;
- mHttpClientConnection = openConnection(req);
- if (mHttpClientConnection != null) {
- mHttpClientConnection.setSocketTimeout(SOCKET_TIMEOUT);
- mHttpContext.setAttribute(HTTP_CONNECTION,
- mHttpClientConnection);
- } else {
- // we tried to do SSL tunneling, failed,
- // and need to drop the request;
- // we have already informed the handler
- req.mFailCount = RETRY_REQUEST_LIMIT;
- return false;
- }
- } catch (UnknownHostException e) {
- if (HttpLog.LOGV) HttpLog.v("Failed to open connection");
- error = EventHandler.ERROR_LOOKUP;
- exception = e;
- } catch (IllegalArgumentException e) {
- if (HttpLog.LOGV) HttpLog.v("Illegal argument exception");
- error = EventHandler.ERROR_CONNECT;
- req.mFailCount = RETRY_REQUEST_LIMIT;
- exception = e;
- } catch (SSLConnectionClosedByUserException e) {
- // hack: if we have an SSL connection failure,
- // we don't want to reconnect
- req.mFailCount = RETRY_REQUEST_LIMIT;
- // no error message
- return false;
- } catch (SSLHandshakeException e) {
- // hack: if we have an SSL connection failure,
- // we don't want to reconnect
- req.mFailCount = RETRY_REQUEST_LIMIT;
- if (HttpLog.LOGV) HttpLog.v(
- "SSL exception performing handshake");
- error = EventHandler.ERROR_FAILED_SSL_HANDSHAKE;
- exception = e;
- } catch (IOException e) {
- error = EventHandler.ERROR_CONNECT;
- exception = e;
- }
-
- if (HttpLog.LOGV) {
- long now2 = SystemClock.uptimeMillis();
- HttpLog.v("Connection.openHttpConnection() " +
- (now2 - now) + " " + mHost);
- }
-
- if (error == EventHandler.OK) {
- return true;
- } else {
- if (req.mFailCount < RETRY_REQUEST_LIMIT) {
- // requeue
- mRequestFeeder.requeueRequest(req);
- req.mFailCount++;
- } else {
- httpFailure(req, error, exception);
- }
- return error == EventHandler.OK;
- }
- }
-
- /**
- * Helper. Calls the mEventHandler's error() method only if
- * request failed permanently. Increments mFailcount on failure.
- *
- * Increments failcount only if the network is believed to be
- * connected
- *
- * @return true if request can be retried (less than
- * RETRY_REQUEST_LIMIT failures have occurred).
- */
- private boolean httpFailure(Request req, int errorId, Exception e) {
- boolean ret = true;
-
- // e.printStackTrace();
- if (HttpLog.LOGV) HttpLog.v(
- "httpFailure() ******* " + e + " count " + req.mFailCount +
- " " + mHost + " " + req.getUri());
-
- if (++req.mFailCount >= RETRY_REQUEST_LIMIT) {
- ret = false;
- String error;
- if (errorId < 0) {
- error = getEventHandlerErrorString(errorId);
- } else {
- Throwable cause = e.getCause();
- error = cause != null ? cause.toString() : e.getMessage();
- }
- req.mEventHandler.error(errorId, error);
- req.complete();
- }
-
- closeConnection();
- mHttpContext.removeAttribute(HTTP_CONNECTION);
-
- return ret;
- }
-
- private static String getEventHandlerErrorString(int errorId) {
- switch (errorId) {
- case EventHandler.OK:
- return "OK";
-
- case EventHandler.ERROR:
- return "ERROR";
-
- case EventHandler.ERROR_LOOKUP:
- return "ERROR_LOOKUP";
-
- case EventHandler.ERROR_UNSUPPORTED_AUTH_SCHEME:
- return "ERROR_UNSUPPORTED_AUTH_SCHEME";
-
- case EventHandler.ERROR_AUTH:
- return "ERROR_AUTH";
-
- case EventHandler.ERROR_PROXYAUTH:
- return "ERROR_PROXYAUTH";
-
- case EventHandler.ERROR_CONNECT:
- return "ERROR_CONNECT";
-
- case EventHandler.ERROR_IO:
- return "ERROR_IO";
-
- case EventHandler.ERROR_TIMEOUT:
- return "ERROR_TIMEOUT";
-
- case EventHandler.ERROR_REDIRECT_LOOP:
- return "ERROR_REDIRECT_LOOP";
-
- case EventHandler.ERROR_UNSUPPORTED_SCHEME:
- return "ERROR_UNSUPPORTED_SCHEME";
-
- case EventHandler.ERROR_FAILED_SSL_HANDSHAKE:
- return "ERROR_FAILED_SSL_HANDSHAKE";
-
- case EventHandler.ERROR_BAD_URL:
- return "ERROR_BAD_URL";
-
- case EventHandler.FILE_ERROR:
- return "FILE_ERROR";
-
- case EventHandler.FILE_NOT_FOUND_ERROR:
- return "FILE_NOT_FOUND_ERROR";
-
- case EventHandler.TOO_MANY_REQUESTS_ERROR:
- return "TOO_MANY_REQUESTS_ERROR";
-
- default:
- return "UNKNOWN_ERROR";
- }
- }
-
- HttpContext getHttpContext() {
- return mHttpContext;
- }
-
- /**
- * Use same logic as ConnectionReuseStrategy
- * @see ConnectionReuseStrategy
- */
- private boolean keepAlive(HttpEntity entity,
- ProtocolVersion ver, int connType, final HttpContext context) {
- org.apache.http.HttpConnection conn = (org.apache.http.HttpConnection)
- context.getAttribute(ExecutionContext.HTTP_CONNECTION);
-
- if (conn != null && !conn.isOpen())
- return false;
- // do NOT check for stale connection, that is an expensive operation
-
- if (entity != null) {
- if (entity.getContentLength() < 0) {
- if (!entity.isChunked() || ver.lessEquals(HttpVersion.HTTP_1_0)) {
- // if the content length is not known and is not chunk
- // encoded, the connection cannot be reused
- return false;
- }
- }
- }
- // Check for 'Connection' directive
- if (connType == Headers.CONN_CLOSE) {
- return false;
- } else if (connType == Headers.CONN_KEEP_ALIVE) {
- return true;
- }
- // Resorting to protocol version default close connection policy
- return !ver.lessEquals(HttpVersion.HTTP_1_0);
- }
-
- void setCanPersist(HttpEntity entity, ProtocolVersion ver, int connType) {
- mCanPersist = keepAlive(entity, ver, connType, mHttpContext);
- }
-
- void setCanPersist(boolean canPersist) {
- mCanPersist = canPersist;
- }
-
- boolean getCanPersist() {
- return mCanPersist;
- }
-
- /** typically http or https... set by subclass */
- abstract String getScheme();
- abstract void closeConnection();
- abstract AndroidHttpClientConnection openConnection(Request req) throws IOException;
-
- /**
- * Prints request queue to log, for debugging.
- * returns request count
- */
- public synchronized String toString() {
- return mHost.toString();
- }
-
- byte[] getBuf() {
- if (mBuf == null) mBuf = new byte[8192];
- return mBuf;
- }
-
-}
diff --git a/core/java/android/net/http/ConnectionThread.java b/core/java/android/net/http/ConnectionThread.java
deleted file mode 100644
index d825530..0000000
--- a/core/java/android/net/http/ConnectionThread.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import android.content.Context;
-import android.os.SystemClock;
-
-import java.lang.Thread;
-
-/**
- * {@hide}
- */
-class ConnectionThread extends Thread {
-
- static final int WAIT_TIMEOUT = 5000;
- static final int WAIT_TICK = 1000;
-
- // Performance probe
- long mCurrentThreadTime;
- long mTotalThreadTime;
-
- private boolean mWaiting;
- private volatile boolean mRunning = true;
- private Context mContext;
- private RequestQueue.ConnectionManager mConnectionManager;
- private RequestFeeder mRequestFeeder;
-
- private int mId;
- Connection mConnection;
-
- ConnectionThread(Context context,
- int id,
- RequestQueue.ConnectionManager connectionManager,
- RequestFeeder requestFeeder) {
- super();
- mContext = context;
- setName("http" + id);
- mId = id;
- mConnectionManager = connectionManager;
- mRequestFeeder = requestFeeder;
- }
-
- void requestStop() {
- synchronized (mRequestFeeder) {
- mRunning = false;
- mRequestFeeder.notify();
- }
- }
-
- /**
- * Loop until app shutdown. Runs connections in priority
- * order.
- */
- public void run() {
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_DEFAULT +
- android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
-
- // these are used to get performance data. When it is not in the timing,
- // mCurrentThreadTime is 0. When it starts timing, mCurrentThreadTime is
- // first set to -1, it will be set to the current thread time when the
- // next request starts.
- mCurrentThreadTime = 0;
- mTotalThreadTime = 0;
-
- while (mRunning) {
- if (mCurrentThreadTime == -1) {
- mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
- }
-
- Request request;
-
- /* Get a request to process */
- request = mRequestFeeder.getRequest();
-
- /* wait for work */
- if (request == null) {
- synchronized(mRequestFeeder) {
- if (HttpLog.LOGV) HttpLog.v("ConnectionThread: Waiting for work");
- mWaiting = true;
- try {
- mRequestFeeder.wait();
- } catch (InterruptedException e) {
- }
- mWaiting = false;
- if (mCurrentThreadTime != 0) {
- mCurrentThreadTime = SystemClock
- .currentThreadTimeMillis();
- }
- }
- } else {
- if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
- request.mHost + " " + request );
-
- mConnection = mConnectionManager.getConnection(mContext,
- request.mHost);
- mConnection.processRequests(request);
- if (mConnection.getCanPersist()) {
- if (!mConnectionManager.recycleConnection(mConnection)) {
- mConnection.closeConnection();
- }
- } else {
- mConnection.closeConnection();
- }
- mConnection = null;
-
- if (mCurrentThreadTime > 0) {
- long start = mCurrentThreadTime;
- mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
- mTotalThreadTime += mCurrentThreadTime - start;
- }
- }
-
- }
- }
-
- public synchronized String toString() {
- String con = mConnection == null ? "" : mConnection.toString();
- String active = mWaiting ? "w" : "a";
- return "cid " + mId + " " + active + " " + con;
- }
-
-}
diff --git a/core/java/android/net/http/DelegatingSSLSession.java b/core/java/android/net/http/DelegatingSSLSession.java
deleted file mode 100644
index 98fbe21..0000000
--- a/core/java/android/net/http/DelegatingSSLSession.java
+++ /dev/null
@@ -1,158 +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.http;
-
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * This is only used when a {@code certificate} is available but usage
- * requires a {@link SSLSession}.
- *
- * @hide
- */
-public class DelegatingSSLSession implements SSLSession {
- protected DelegatingSSLSession() {
- }
-
- public static class CertificateWrap extends DelegatingSSLSession {
- private final Certificate mCertificate;
-
- public CertificateWrap(Certificate certificate) {
- mCertificate = certificate;
- }
-
- @Override
- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
- return new Certificate[] { mCertificate };
- }
- }
-
-
- @Override
- public int getApplicationBufferSize() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getCipherSuite() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public long getCreationTime() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public byte[] getId() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public long getLastAccessedTime() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Certificate[] getLocalCertificates() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Principal getLocalPrincipal() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getPacketBufferSize() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public javax.security.cert.X509Certificate[] getPeerCertificateChain()
- throws SSLPeerUnverifiedException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getPeerHost() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getPeerPort() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getProtocol() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SSLSessionContext getSessionContext() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object getValue(String name) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String[] getValueNames() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void invalidate() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isValid() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void putValue(String name, Object value) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void removeValue(String name) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/core/java/android/net/http/EventHandler.java b/core/java/android/net/http/EventHandler.java
deleted file mode 100644
index 3fd471d..0000000
--- a/core/java/android/net/http/EventHandler.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-
-/**
- * Callbacks in this interface are made as an HTTP request is
- * processed. The normal order of callbacks is status(), headers(),
- * then multiple data() then endData(). handleSslErrorRequest(), if
- * there is an SSL certificate error. error() can occur anywhere
- * in the transaction.
- *
- * {@hide}
- */
-
-public interface EventHandler {
-
- /**
- * Error codes used in the error() callback. Positive error codes
- * are reserved for codes sent by http servers. Negative error
- * codes are connection/parsing failures, etc.
- */
-
- /** Success */
- public static final int OK = 0;
- /** Generic error */
- public static final int ERROR = -1;
- /** Server or proxy hostname lookup failed */
- public static final int ERROR_LOOKUP = -2;
- /** Unsupported authentication scheme (ie, not basic or digest) */
- public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3;
- /** User authentication failed on server */
- public static final int ERROR_AUTH = -4;
- /** User authentication failed on proxy */
- public static final int ERROR_PROXYAUTH = -5;
- /** Could not connect to server */
- public static final int ERROR_CONNECT = -6;
- /** Failed to write to or read from server */
- public static final int ERROR_IO = -7;
- /** Connection timed out */
- public static final int ERROR_TIMEOUT = -8;
- /** Too many redirects */
- public static final int ERROR_REDIRECT_LOOP = -9;
- /** Unsupported URI scheme (ie, not http, https, etc) */
- public static final int ERROR_UNSUPPORTED_SCHEME = -10;
- /** Failed to perform SSL handshake */
- public static final int ERROR_FAILED_SSL_HANDSHAKE = -11;
- /** Bad URL */
- public static final int ERROR_BAD_URL = -12;
- /** Generic file error for file:/// loads */
- public static final int FILE_ERROR = -13;
- /** File not found error for file:/// loads */
- public static final int FILE_NOT_FOUND_ERROR = -14;
- /** Too many requests queued */
- public static final int TOO_MANY_REQUESTS_ERROR = -15;
-
- /**
- * Called after status line has been sucessfully processed.
- * @param major_version HTTP version advertised by server. major
- * is the part before the "."
- * @param minor_version HTTP version advertised by server. minor
- * is the part after the "."
- * @param code HTTP Status code. See RFC 2616.
- * @param reason_phrase Textual explanation sent by server
- */
- public void status(int major_version,
- int minor_version,
- int code,
- String reason_phrase);
-
- /**
- * Called after all headers are successfully processed.
- */
- public void headers(Headers headers);
-
- /**
- * An array containing all or part of the http body as read from
- * the server.
- * @param data A byte array containing the content
- * @param len The length of valid content in data
- *
- * Note: chunked and compressed encodings are handled within
- * android.net.http. Decoded data is passed through this
- * interface.
- */
- public void data(byte[] data, int len);
-
- /**
- * Called when the document is completely read. No more data()
- * callbacks will be made after this call
- */
- public void endData();
-
- /**
- * SSL certificate callback called before resource request is
- * made, which will be null for insecure connection.
- */
- public void certificate(SslCertificate certificate);
-
- /**
- * There was trouble.
- * @param id One of the error codes defined below
- * @param description of error
- */
- public void error(int id, String description);
-
- /**
- * SSL certificate error callback. Handles SSL error(s) on the way
- * up to the user. The callback has to make sure that restartConnection() is called,
- * otherwise the connection will be suspended indefinitely.
- * @return True if the callback can handle the error, which means it will
- * call restartConnection() to unblock the thread later,
- * otherwise return false.
- */
- public boolean handleSslErrorRequest(SslError error);
-
-}
diff --git a/core/java/android/net/http/Headers.java b/core/java/android/net/http/Headers.java
deleted file mode 100644
index 0f8b105..0000000
--- a/core/java/android/net/http/Headers.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import android.util.Log;
-
-import java.util.ArrayList;
-
-import org.apache.http.HeaderElement;
-import org.apache.http.entity.ContentLengthStrategy;
-import org.apache.http.message.BasicHeaderValueParser;
-import org.apache.http.message.ParserCursor;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.CharArrayBuffer;
-
-/**
- * Manages received headers
- *
- * {@hide}
- */
-public final class Headers {
- private static final String LOGTAG = "Http";
-
- // header parsing constant
- /**
- * indicate HTTP 1.0 connection close after the response
- */
- public final static int CONN_CLOSE = 1;
- /**
- * indicate HTTP 1.1 connection keep alive
- */
- public final static int CONN_KEEP_ALIVE = 2;
-
- // initial values.
- public final static int NO_CONN_TYPE = 0;
- public final static long NO_TRANSFER_ENCODING = 0;
- public final static long NO_CONTENT_LENGTH = -1;
-
- // header strings
- public final static String TRANSFER_ENCODING = "transfer-encoding";
- public final static String CONTENT_LEN = "content-length";
- public final static String CONTENT_TYPE = "content-type";
- public final static String CONTENT_ENCODING = "content-encoding";
- public final static String CONN_DIRECTIVE = "connection";
-
- public final static String LOCATION = "location";
- public final static String PROXY_CONNECTION = "proxy-connection";
-
- public final static String WWW_AUTHENTICATE = "www-authenticate";
- public final static String PROXY_AUTHENTICATE = "proxy-authenticate";
- public final static String CONTENT_DISPOSITION = "content-disposition";
- public final static String ACCEPT_RANGES = "accept-ranges";
- public final static String EXPIRES = "expires";
- public final static String CACHE_CONTROL = "cache-control";
- public final static String LAST_MODIFIED = "last-modified";
- public final static String ETAG = "etag";
- public final static String SET_COOKIE = "set-cookie";
- public final static String PRAGMA = "pragma";
- public final static String REFRESH = "refresh";
- public final static String X_PERMITTED_CROSS_DOMAIN_POLICIES = "x-permitted-cross-domain-policies";
-
- // following hash are generated by String.hashCode()
- private final static int HASH_TRANSFER_ENCODING = 1274458357;
- private final static int HASH_CONTENT_LEN = -1132779846;
- private final static int HASH_CONTENT_TYPE = 785670158;
- private final static int HASH_CONTENT_ENCODING = 2095084583;
- private final static int HASH_CONN_DIRECTIVE = -775651618;
- private final static int HASH_LOCATION = 1901043637;
- private final static int HASH_PROXY_CONNECTION = 285929373;
- private final static int HASH_WWW_AUTHENTICATE = -243037365;
- private final static int HASH_PROXY_AUTHENTICATE = -301767724;
- private final static int HASH_CONTENT_DISPOSITION = -1267267485;
- private final static int HASH_ACCEPT_RANGES = 1397189435;
- private final static int HASH_EXPIRES = -1309235404;
- private final static int HASH_CACHE_CONTROL = -208775662;
- private final static int HASH_LAST_MODIFIED = 150043680;
- private final static int HASH_ETAG = 3123477;
- private final static int HASH_SET_COOKIE = 1237214767;
- private final static int HASH_PRAGMA = -980228804;
- private final static int HASH_REFRESH = 1085444827;
- private final static int HASH_X_PERMITTED_CROSS_DOMAIN_POLICIES = -1345594014;
-
- // keep any headers that require direct access in a presized
- // string array
- private final static int IDX_TRANSFER_ENCODING = 0;
- private final static int IDX_CONTENT_LEN = 1;
- private final static int IDX_CONTENT_TYPE = 2;
- private final static int IDX_CONTENT_ENCODING = 3;
- private final static int IDX_CONN_DIRECTIVE = 4;
- private final static int IDX_LOCATION = 5;
- private final static int IDX_PROXY_CONNECTION = 6;
- private final static int IDX_WWW_AUTHENTICATE = 7;
- private final static int IDX_PROXY_AUTHENTICATE = 8;
- private final static int IDX_CONTENT_DISPOSITION = 9;
- private final static int IDX_ACCEPT_RANGES = 10;
- private final static int IDX_EXPIRES = 11;
- private final static int IDX_CACHE_CONTROL = 12;
- private final static int IDX_LAST_MODIFIED = 13;
- private final static int IDX_ETAG = 14;
- private final static int IDX_SET_COOKIE = 15;
- private final static int IDX_PRAGMA = 16;
- private final static int IDX_REFRESH = 17;
- private final static int IDX_X_PERMITTED_CROSS_DOMAIN_POLICIES = 18;
-
- private final static int HEADER_COUNT = 19;
-
- /* parsed values */
- private long transferEncoding;
- private long contentLength; // Content length of the incoming data
- private int connectionType;
- private ArrayList<String> cookies = new ArrayList<String>(2);
-
- private String[] mHeaders = new String[HEADER_COUNT];
- private final static String[] sHeaderNames = {
- TRANSFER_ENCODING,
- CONTENT_LEN,
- CONTENT_TYPE,
- CONTENT_ENCODING,
- CONN_DIRECTIVE,
- LOCATION,
- PROXY_CONNECTION,
- WWW_AUTHENTICATE,
- PROXY_AUTHENTICATE,
- CONTENT_DISPOSITION,
- ACCEPT_RANGES,
- EXPIRES,
- CACHE_CONTROL,
- LAST_MODIFIED,
- ETAG,
- SET_COOKIE,
- PRAGMA,
- REFRESH,
- X_PERMITTED_CROSS_DOMAIN_POLICIES
- };
-
- // Catch-all for headers not explicitly handled
- private ArrayList<String> mExtraHeaderNames = new ArrayList<String>(4);
- private ArrayList<String> mExtraHeaderValues = new ArrayList<String>(4);
-
- public Headers() {
- transferEncoding = NO_TRANSFER_ENCODING;
- contentLength = NO_CONTENT_LENGTH;
- connectionType = NO_CONN_TYPE;
- }
-
- public void parseHeader(CharArrayBuffer buffer) {
- int pos = setLowercaseIndexOf(buffer, ':');
- if (pos == -1) {
- return;
- }
- String name = buffer.substringTrimmed(0, pos);
- if (name.length() == 0) {
- return;
- }
- pos++;
-
- String val = buffer.substringTrimmed(pos, buffer.length());
- if (HttpLog.LOGV) {
- HttpLog.v("hdr " + buffer.length() + " " + buffer);
- }
-
- switch (name.hashCode()) {
- case HASH_TRANSFER_ENCODING:
- if (name.equals(TRANSFER_ENCODING)) {
- mHeaders[IDX_TRANSFER_ENCODING] = val;
- HeaderElement[] encodings = BasicHeaderValueParser.DEFAULT
- .parseElements(buffer, new ParserCursor(pos,
- buffer.length()));
- // The chunked encoding must be the last one applied RFC2616,
- // 14.41
- int len = encodings.length;
- if (HTTP.IDENTITY_CODING.equalsIgnoreCase(val)) {
- transferEncoding = ContentLengthStrategy.IDENTITY;
- } else if ((len > 0)
- && (HTTP.CHUNK_CODING
- .equalsIgnoreCase(encodings[len - 1].getName()))) {
- transferEncoding = ContentLengthStrategy.CHUNKED;
- } else {
- transferEncoding = ContentLengthStrategy.IDENTITY;
- }
- }
- break;
- case HASH_CONTENT_LEN:
- if (name.equals(CONTENT_LEN)) {
- mHeaders[IDX_CONTENT_LEN] = val;
- try {
- contentLength = Long.parseLong(val);
- } catch (NumberFormatException e) {
- if (false) {
- Log.v(LOGTAG, "Headers.headers(): error parsing"
- + " content length: " + buffer.toString());
- }
- }
- }
- break;
- case HASH_CONTENT_TYPE:
- if (name.equals(CONTENT_TYPE)) {
- mHeaders[IDX_CONTENT_TYPE] = val;
- }
- break;
- case HASH_CONTENT_ENCODING:
- if (name.equals(CONTENT_ENCODING)) {
- mHeaders[IDX_CONTENT_ENCODING] = val;
- }
- break;
- case HASH_CONN_DIRECTIVE:
- if (name.equals(CONN_DIRECTIVE)) {
- mHeaders[IDX_CONN_DIRECTIVE] = val;
- setConnectionType(buffer, pos);
- }
- break;
- case HASH_LOCATION:
- if (name.equals(LOCATION)) {
- mHeaders[IDX_LOCATION] = val;
- }
- break;
- case HASH_PROXY_CONNECTION:
- if (name.equals(PROXY_CONNECTION)) {
- mHeaders[IDX_PROXY_CONNECTION] = val;
- setConnectionType(buffer, pos);
- }
- break;
- case HASH_WWW_AUTHENTICATE:
- if (name.equals(WWW_AUTHENTICATE)) {
- mHeaders[IDX_WWW_AUTHENTICATE] = val;
- }
- break;
- case HASH_PROXY_AUTHENTICATE:
- if (name.equals(PROXY_AUTHENTICATE)) {
- mHeaders[IDX_PROXY_AUTHENTICATE] = val;
- }
- break;
- case HASH_CONTENT_DISPOSITION:
- if (name.equals(CONTENT_DISPOSITION)) {
- mHeaders[IDX_CONTENT_DISPOSITION] = val;
- }
- break;
- case HASH_ACCEPT_RANGES:
- if (name.equals(ACCEPT_RANGES)) {
- mHeaders[IDX_ACCEPT_RANGES] = val;
- }
- break;
- case HASH_EXPIRES:
- if (name.equals(EXPIRES)) {
- mHeaders[IDX_EXPIRES] = val;
- }
- break;
- case HASH_CACHE_CONTROL:
- if (name.equals(CACHE_CONTROL)) {
- // In case where we receive more than one header, create a ',' separated list.
- // This should be ok, according to RFC 2616 chapter 4.2
- if (mHeaders[IDX_CACHE_CONTROL] != null &&
- mHeaders[IDX_CACHE_CONTROL].length() > 0) {
- mHeaders[IDX_CACHE_CONTROL] += (',' + val);
- } else {
- mHeaders[IDX_CACHE_CONTROL] = val;
- }
- }
- break;
- case HASH_LAST_MODIFIED:
- if (name.equals(LAST_MODIFIED)) {
- mHeaders[IDX_LAST_MODIFIED] = val;
- }
- break;
- case HASH_ETAG:
- if (name.equals(ETAG)) {
- mHeaders[IDX_ETAG] = val;
- }
- break;
- case HASH_SET_COOKIE:
- if (name.equals(SET_COOKIE)) {
- mHeaders[IDX_SET_COOKIE] = val;
- cookies.add(val);
- }
- break;
- case HASH_PRAGMA:
- if (name.equals(PRAGMA)) {
- mHeaders[IDX_PRAGMA] = val;
- }
- break;
- case HASH_REFRESH:
- if (name.equals(REFRESH)) {
- mHeaders[IDX_REFRESH] = val;
- }
- break;
- case HASH_X_PERMITTED_CROSS_DOMAIN_POLICIES:
- if (name.equals(X_PERMITTED_CROSS_DOMAIN_POLICIES)) {
- mHeaders[IDX_X_PERMITTED_CROSS_DOMAIN_POLICIES] = val;
- }
- break;
- default:
- mExtraHeaderNames.add(name);
- mExtraHeaderValues.add(val);
- }
- }
-
- public long getTransferEncoding() {
- return transferEncoding;
- }
-
- public long getContentLength() {
- return contentLength;
- }
-
- public int getConnectionType() {
- return connectionType;
- }
-
- public String getContentType() {
- return mHeaders[IDX_CONTENT_TYPE];
- }
-
- public String getContentEncoding() {
- return mHeaders[IDX_CONTENT_ENCODING];
- }
-
- public String getLocation() {
- return mHeaders[IDX_LOCATION];
- }
-
- public String getWwwAuthenticate() {
- return mHeaders[IDX_WWW_AUTHENTICATE];
- }
-
- public String getProxyAuthenticate() {
- return mHeaders[IDX_PROXY_AUTHENTICATE];
- }
-
- public String getContentDisposition() {
- return mHeaders[IDX_CONTENT_DISPOSITION];
- }
-
- public String getAcceptRanges() {
- return mHeaders[IDX_ACCEPT_RANGES];
- }
-
- public String getExpires() {
- return mHeaders[IDX_EXPIRES];
- }
-
- public String getCacheControl() {
- return mHeaders[IDX_CACHE_CONTROL];
- }
-
- public String getLastModified() {
- return mHeaders[IDX_LAST_MODIFIED];
- }
-
- public String getEtag() {
- return mHeaders[IDX_ETAG];
- }
-
- public ArrayList<String> getSetCookie() {
- return this.cookies;
- }
-
- public String getPragma() {
- return mHeaders[IDX_PRAGMA];
- }
-
- public String getRefresh() {
- return mHeaders[IDX_REFRESH];
- }
-
- public String getXPermittedCrossDomainPolicies() {
- return mHeaders[IDX_X_PERMITTED_CROSS_DOMAIN_POLICIES];
- }
-
- public void setContentLength(long value) {
- this.contentLength = value;
- }
-
- public void setContentType(String value) {
- mHeaders[IDX_CONTENT_TYPE] = value;
- }
-
- public void setContentEncoding(String value) {
- mHeaders[IDX_CONTENT_ENCODING] = value;
- }
-
- public void setLocation(String value) {
- mHeaders[IDX_LOCATION] = value;
- }
-
- public void setWwwAuthenticate(String value) {
- mHeaders[IDX_WWW_AUTHENTICATE] = value;
- }
-
- public void setProxyAuthenticate(String value) {
- mHeaders[IDX_PROXY_AUTHENTICATE] = value;
- }
-
- public void setContentDisposition(String value) {
- mHeaders[IDX_CONTENT_DISPOSITION] = value;
- }
-
- public void setAcceptRanges(String value) {
- mHeaders[IDX_ACCEPT_RANGES] = value;
- }
-
- public void setExpires(String value) {
- mHeaders[IDX_EXPIRES] = value;
- }
-
- public void setCacheControl(String value) {
- mHeaders[IDX_CACHE_CONTROL] = value;
- }
-
- public void setLastModified(String value) {
- mHeaders[IDX_LAST_MODIFIED] = value;
- }
-
- public void setEtag(String value) {
- mHeaders[IDX_ETAG] = value;
- }
-
- public void setXPermittedCrossDomainPolicies(String value) {
- mHeaders[IDX_X_PERMITTED_CROSS_DOMAIN_POLICIES] = value;
- }
-
- public interface HeaderCallback {
- public void header(String name, String value);
- }
-
- /**
- * Reports all non-null headers to the callback
- */
- public void getHeaders(HeaderCallback hcb) {
- for (int i = 0; i < HEADER_COUNT; i++) {
- String h = mHeaders[i];
- if (h != null) {
- hcb.header(sHeaderNames[i], h);
- }
- }
- int extraLen = mExtraHeaderNames.size();
- for (int i = 0; i < extraLen; i++) {
- if (false) {
- HttpLog.v("Headers.getHeaders() extra: " + i + " " +
- mExtraHeaderNames.get(i) + " " + mExtraHeaderValues.get(i));
- }
- hcb.header(mExtraHeaderNames.get(i),
- mExtraHeaderValues.get(i));
- }
-
- }
-
- private void setConnectionType(CharArrayBuffer buffer, int pos) {
- if (containsIgnoreCaseTrimmed(buffer, pos, HTTP.CONN_CLOSE)) {
- connectionType = CONN_CLOSE;
- } else if (containsIgnoreCaseTrimmed(
- buffer, pos, HTTP.CONN_KEEP_ALIVE)) {
- connectionType = CONN_KEEP_ALIVE;
- }
- }
-
-
- /**
- * Returns true if the buffer contains the given string. Ignores leading
- * whitespace and case.
- *
- * @param buffer to search
- * @param beginIndex index at which we should start
- * @param str to search for
- */
- static boolean containsIgnoreCaseTrimmed(CharArrayBuffer buffer,
- int beginIndex, final String str) {
- int len = buffer.length();
- char[] chars = buffer.buffer();
- while (beginIndex < len && HTTP.isWhitespace(chars[beginIndex])) {
- beginIndex++;
- }
- int size = str.length();
- boolean ok = len >= (beginIndex + size);
- for (int j=0; ok && (j < size); j++) {
- char a = chars[beginIndex + j];
- char b = str.charAt(j);
- if (a != b) {
- a = Character.toLowerCase(a);
- b = Character.toLowerCase(b);
- ok = a == b;
- }
- }
-
- return true;
- }
-
- /**
- * Returns index of first occurence ch. Lower cases characters leading up
- * to first occurrence of ch.
- */
- static int setLowercaseIndexOf(CharArrayBuffer buffer, final int ch) {
-
- int beginIndex = 0;
- int endIndex = buffer.length();
- char[] chars = buffer.buffer();
-
- for (int i = beginIndex; i < endIndex; i++) {
- char current = chars[i];
- if (current == ch) {
- return i;
- } else {
- chars[i] = Character.toLowerCase(current);
- }
- }
- return -1;
- }
-}
diff --git a/core/java/android/net/http/HttpAuthHeader.java b/core/java/android/net/http/HttpAuthHeader.java
deleted file mode 100644
index 3abac23..0000000
--- a/core/java/android/net/http/HttpAuthHeader.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * 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.net.http;
-
-import java.util.Locale;
-
-/**
- * HttpAuthHeader: a class to store HTTP authentication-header parameters.
- * For more information, see: RFC 2617: HTTP Authentication.
- *
- * {@hide}
- */
-public class HttpAuthHeader {
- /**
- * Possible HTTP-authentication header tokens to search for:
- */
- public final static String BASIC_TOKEN = "Basic";
- public final static String DIGEST_TOKEN = "Digest";
-
- private final static String REALM_TOKEN = "realm";
- private final static String NONCE_TOKEN = "nonce";
- private final static String STALE_TOKEN = "stale";
- private final static String OPAQUE_TOKEN = "opaque";
- private final static String QOP_TOKEN = "qop";
- private final static String ALGORITHM_TOKEN = "algorithm";
-
- /**
- * An authentication scheme. We currently support two different schemes:
- * HttpAuthHeader.BASIC - basic, and
- * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
- */
- private int mScheme;
-
- public static final int UNKNOWN = 0;
- public static final int BASIC = 1;
- public static final int DIGEST = 2;
-
- /**
- * A flag, indicating that the previous request from the client was
- * rejected because the nonce value was stale. If stale is TRUE
- * (case-insensitive), the client may wish to simply retry the request
- * with a new encrypted response, without reprompting the user for a
- * new username and password.
- */
- private boolean mStale;
-
- /**
- * A string to be displayed to users so they know which username and
- * password to use.
- */
- private String mRealm;
-
- /**
- * A server-specified data string which should be uniquely generated
- * each time a 401 response is made.
- */
- private String mNonce;
-
- /**
- * A string of data, specified by the server, which should be returned
- * by the client unchanged in the Authorization header of subsequent
- * requests with URIs in the same protection space.
- */
- private String mOpaque;
-
- /**
- * This directive is optional, but is made so only for backward
- * compatibility with RFC 2069 [6]; it SHOULD be used by all
- * implementations compliant with this version of the Digest scheme.
- * If present, it is a quoted string of one or more tokens indicating
- * the "quality of protection" values supported by the server. The
- * value "auth" indicates authentication; the value "auth-int"
- * indicates authentication with integrity protection.
- */
- private String mQop;
-
- /**
- * A string indicating a pair of algorithms used to produce the digest
- * and a checksum. If this is not present it is assumed to be "MD5".
- */
- private String mAlgorithm;
-
- /**
- * Is this authentication request a proxy authentication request?
- */
- private boolean mIsProxy;
-
- /**
- * Username string we get from the user.
- */
- private String mUsername;
-
- /**
- * Password string we get from the user.
- */
- private String mPassword;
-
- /**
- * Creates a new HTTP-authentication header object from the
- * input header string.
- * The header string is assumed to contain parameters of at
- * most one authentication-scheme (ensured by the caller).
- */
- public HttpAuthHeader(String header) {
- if (header != null) {
- parseHeader(header);
- }
- }
-
- /**
- * @return True iff this is a proxy authentication header.
- */
- public boolean isProxy() {
- return mIsProxy;
- }
-
- /**
- * Marks this header as a proxy authentication header.
- */
- public void setProxy() {
- mIsProxy = true;
- }
-
- /**
- * @return The username string.
- */
- public String getUsername() {
- return mUsername;
- }
-
- /**
- * Sets the username string.
- */
- public void setUsername(String username) {
- mUsername = username;
- }
-
- /**
- * @return The password string.
- */
- public String getPassword() {
- return mPassword;
- }
-
- /**
- * Sets the password string.
- */
- public void setPassword(String password) {
- mPassword = password;
- }
-
- /**
- * @return True iff this is the BASIC-authentication request.
- */
- public boolean isBasic () {
- return mScheme == BASIC;
- }
-
- /**
- * @return True iff this is the DIGEST-authentication request.
- */
- public boolean isDigest() {
- return mScheme == DIGEST;
- }
-
- /**
- * @return The authentication scheme requested. We currently
- * support two schemes:
- * HttpAuthHeader.BASIC - basic, and
- * HttpAuthHeader.DIGEST - digest (algorithm=MD5, QOP="auth").
- */
- public int getScheme() {
- return mScheme;
- }
-
- /**
- * @return True if indicating that the previous request from
- * the client was rejected because the nonce value was stale.
- */
- public boolean getStale() {
- return mStale;
- }
-
- /**
- * @return The realm value or null if there is none.
- */
- public String getRealm() {
- return mRealm;
- }
-
- /**
- * @return The nonce value or null if there is none.
- */
- public String getNonce() {
- return mNonce;
- }
-
- /**
- * @return The opaque value or null if there is none.
- */
- public String getOpaque() {
- return mOpaque;
- }
-
- /**
- * @return The QOP ("quality-of_protection") value or null if
- * there is none. The QOP value is always lower-case.
- */
- public String getQop() {
- return mQop;
- }
-
- /**
- * @return The name of the algorithm used or null if there is
- * none. By default, MD5 is used.
- */
- public String getAlgorithm() {
- return mAlgorithm;
- }
-
- /**
- * @return True iff the authentication scheme requested by the
- * server is supported; currently supported schemes:
- * BASIC,
- * DIGEST (only algorithm="md5", no qop or qop="auth).
- */
- public boolean isSupportedScheme() {
- // it is a good idea to enforce non-null realms!
- if (mRealm != null) {
- if (mScheme == BASIC) {
- return true;
- } else {
- if (mScheme == DIGEST) {
- return
- mAlgorithm.equals("md5") &&
- (mQop == null || mQop.equals("auth"));
- }
- }
- }
-
- return false;
- }
-
- /**
- * Parses the header scheme name and then scheme parameters if
- * the scheme is supported.
- */
- private void parseHeader(String header) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseHeader(): header: " + header);
- }
-
- if (header != null) {
- String parameters = parseScheme(header);
- if (parameters != null) {
- // if we have a supported scheme
- if (mScheme != UNKNOWN) {
- parseParameters(parameters);
- }
- }
- }
- }
-
- /**
- * Parses the authentication scheme name. If we have a Digest
- * scheme, sets the algorithm value to the default of MD5.
- * @return The authentication scheme parameters string to be
- * parsed later (if the scheme is supported) or null if failed
- * to parse the scheme (the header value is null?).
- */
- private String parseScheme(String header) {
- if (header != null) {
- int i = header.indexOf(' ');
- if (i >= 0) {
- String scheme = header.substring(0, i).trim();
- if (scheme.equalsIgnoreCase(DIGEST_TOKEN)) {
- mScheme = DIGEST;
-
- // md5 is the default algorithm!!!
- mAlgorithm = "md5";
- } else {
- if (scheme.equalsIgnoreCase(BASIC_TOKEN)) {
- mScheme = BASIC;
- }
- }
-
- return header.substring(i + 1);
- }
- }
-
- return null;
- }
-
- /**
- * Parses a comma-separated list of authentification scheme
- * parameters.
- */
- private void parseParameters(String parameters) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseParameters():" +
- " parameters: " + parameters);
- }
-
- if (parameters != null) {
- int i;
- do {
- i = parameters.indexOf(',');
- if (i < 0) {
- // have only one parameter
- parseParameter(parameters);
- } else {
- parseParameter(parameters.substring(0, i));
- parameters = parameters.substring(i + 1);
- }
- } while (i >= 0);
- }
- }
-
- /**
- * Parses a single authentication scheme parameter. The parameter
- * string is expected to follow the format: PARAMETER=VALUE.
- */
- private void parseParameter(String parameter) {
- if (parameter != null) {
- // here, we are looking for the 1st occurence of '=' only!!!
- int i = parameter.indexOf('=');
- if (i >= 0) {
- String token = parameter.substring(0, i).trim();
- String value =
- trimDoubleQuotesIfAny(parameter.substring(i + 1).trim());
-
- if (HttpLog.LOGV) {
- HttpLog.v("HttpAuthHeader.parseParameter():" +
- " token: " + token +
- " value: " + value);
- }
-
- if (token.equalsIgnoreCase(REALM_TOKEN)) {
- mRealm = value;
- } else {
- if (mScheme == DIGEST) {
- parseParameter(token, value);
- }
- }
- }
- }
- }
-
- /**
- * If the token is a known parameter name, parses and initializes
- * the token value.
- */
- private void parseParameter(String token, String value) {
- if (token != null && value != null) {
- if (token.equalsIgnoreCase(NONCE_TOKEN)) {
- mNonce = value;
- return;
- }
-
- if (token.equalsIgnoreCase(STALE_TOKEN)) {
- parseStale(value);
- return;
- }
-
- if (token.equalsIgnoreCase(OPAQUE_TOKEN)) {
- mOpaque = value;
- return;
- }
-
- if (token.equalsIgnoreCase(QOP_TOKEN)) {
- mQop = value.toLowerCase(Locale.ROOT);
- return;
- }
-
- if (token.equalsIgnoreCase(ALGORITHM_TOKEN)) {
- mAlgorithm = value.toLowerCase(Locale.ROOT);
- return;
- }
- }
- }
-
- /**
- * Parses and initializes the 'stale' paramer value. Any value
- * different from case-insensitive "true" is considered "false".
- */
- private void parseStale(String value) {
- if (value != null) {
- if (value.equalsIgnoreCase("true")) {
- mStale = true;
- }
- }
- }
-
- /**
- * Trims double-quotes around a parameter value if there are any.
- * @return The string value without the outermost pair of double-
- * quotes or null if the original value is null.
- */
- static private String trimDoubleQuotesIfAny(String value) {
- if (value != null) {
- int len = value.length();
- if (len > 2 &&
- value.charAt(0) == '\"' && value.charAt(len - 1) == '\"') {
- return value.substring(1, len - 1);
- }
- }
-
- return value;
- }
-}
diff --git a/core/java/android/net/http/HttpConnection.java b/core/java/android/net/http/HttpConnection.java
deleted file mode 100644
index edf8fed3..0000000
--- a/core/java/android/net/http/HttpConnection.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.net.http;
-
-import android.content.Context;
-
-import java.net.Socket;
-import java.io.IOException;
-
-import org.apache.http.HttpHost;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-
-/**
- * A requestConnection connecting to a normal (non secure) http server
- *
- * {@hide}
- */
-class HttpConnection extends Connection {
-
- HttpConnection(Context context, HttpHost host,
- RequestFeeder requestFeeder) {
- super(context, host, requestFeeder);
- }
-
- /**
- * Opens the connection to a http server
- *
- * @return the opened low level connection
- * @throws IOException if the connection fails for any reason.
- */
- @Override
- AndroidHttpClientConnection openConnection(Request req) throws IOException {
-
- // Update the certificate info (connection not secure - set to null)
- EventHandler eventHandler = req.getEventHandler();
- mCertificate = null;
- eventHandler.certificate(mCertificate);
-
- AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
- BasicHttpParams params = new BasicHttpParams();
- Socket sock = new Socket(mHost.getHostName(), mHost.getPort());
- params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
- conn.bind(sock, params);
- return conn;
- }
-
- /**
- * Closes the low level connection.
- *
- * If an exception is thrown then it is assumed that the
- * connection will have been closed (to the extent possible)
- * anyway and the caller does not need to take any further action.
- *
- */
- void closeConnection() {
- try {
- if (mHttpClientConnection != null && mHttpClientConnection.isOpen()) {
- mHttpClientConnection.close();
- }
- } catch (IOException e) {
- if (HttpLog.LOGV) HttpLog.v(
- "closeConnection(): failed closing connection " +
- mHost);
- e.printStackTrace();
- }
- }
-
- /**
- * Restart a secure connection suspended waiting for user interaction.
- */
- void restartConnection(boolean abort) {
- // not required for plain http connections
- }
-
- String getScheme() {
- return "http";
- }
-}
diff --git a/core/java/android/net/http/HttpLog.java b/core/java/android/net/http/HttpLog.java
deleted file mode 100644
index 0934664..0000000
--- a/core/java/android/net/http/HttpLog.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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-level logging flag
- */
-
-package android.net.http;
-
-import android.os.SystemClock;
-
-import android.util.Log;
-
-/**
- * {@hide}
- */
-class HttpLog {
- private final static String LOGTAG = "http";
-
- private static final boolean DEBUG = false;
- static final boolean LOGV = false;
-
- static void v(String logMe) {
- Log.v(LOGTAG, SystemClock.uptimeMillis() + " " + Thread.currentThread().getName() + " " + logMe);
- }
-
- static void e(String logMe) {
- Log.e(LOGTAG, logMe);
- }
-}
diff --git a/core/java/android/net/http/HttpResponseCache.java b/core/java/android/net/http/HttpResponseCache.java
index c6c22e7..188287f 100644
--- a/core/java/android/net/http/HttpResponseCache.java
+++ b/core/java/android/net/http/HttpResponseCache.java
@@ -35,8 +35,8 @@
* Caches HTTP and HTTPS responses to the filesystem so they may be reused,
* saving time and bandwidth. This class supports {@link
* java.net.HttpURLConnection} and {@link javax.net.ssl.HttpsURLConnection};
- * there is no platform-provided cache for {@link
- * org.apache.http.impl.client.DefaultHttpClient} or {@link AndroidHttpClient}.
+ * there is no platform-provided cache for {@code DefaultHttpClient} or
+ * {@code AndroidHttpClient}.
*
* <h3>Installing an HTTP response cache</h3>
* Enable caching of all of your application's HTTP requests by installing the
diff --git a/core/java/android/net/http/HttpsConnection.java b/core/java/android/net/http/HttpsConnection.java
deleted file mode 100644
index a8674de..0000000
--- a/core/java/android/net/http/HttpsConnection.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * 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.net.http;
-
-import android.content.Context;
-import android.util.Log;
-import com.android.org.conscrypt.FileClientSessionCache;
-import com.android.org.conscrypt.OpenSSLContextImpl;
-import com.android.org.conscrypt.SSLClientSessionCache;
-import org.apache.http.Header;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpStatus;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.StatusLine;
-import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import java.io.File;
-import java.io.IOException;
-import java.net.Socket;
-import java.security.KeyManagementException;
-import java.security.cert.X509Certificate;
-import java.util.Locale;
-
-/**
- * A Connection connecting to a secure http server or tunneling through
- * a http proxy server to a https server.
- *
- * @hide
- */
-public class HttpsConnection extends Connection {
-
- /**
- * SSL socket factory
- */
- private static SSLSocketFactory mSslSocketFactory = null;
-
- static {
- // This initialization happens in the zygote. It triggers some
- // lazy initialization that can will benefit later invocations of
- // initializeEngine().
- initializeEngine(null);
- }
-
- /**
- * @hide
- *
- * @param sessionDir directory to cache SSL sessions
- */
- public static void initializeEngine(File sessionDir) {
- try {
- SSLClientSessionCache cache = null;
- if (sessionDir != null) {
- Log.d("HttpsConnection", "Caching SSL sessions in "
- + sessionDir + ".");
- cache = FileClientSessionCache.usingDirectory(sessionDir);
- }
-
- OpenSSLContextImpl sslContext = OpenSSLContextImpl.getPreferred();
-
- // here, trust managers is a single trust-all manager
- TrustManager[] trustManagers = new TrustManager[] {
- new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(
- X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(
- X509Certificate[] certs, String authType) {
- }
- }
- };
-
- sslContext.engineInit(null, trustManagers, null);
- sslContext.engineGetClientSessionContext().setPersistentCache(cache);
-
- synchronized (HttpsConnection.class) {
- mSslSocketFactory = sslContext.engineGetSocketFactory();
- }
- } catch (KeyManagementException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private synchronized static SSLSocketFactory getSocketFactory() {
- return mSslSocketFactory;
- }
-
- /**
- * Object to wait on when suspending the SSL connection
- */
- private Object mSuspendLock = new Object();
-
- /**
- * True if the connection is suspended pending the result of asking the
- * user about an error.
- */
- private boolean mSuspended = false;
-
- /**
- * True if the connection attempt should be aborted due to an ssl
- * error.
- */
- private boolean mAborted = false;
-
- // Used when connecting through a proxy.
- private HttpHost mProxyHost;
-
- /**
- * Contructor for a https connection.
- */
- HttpsConnection(Context context, HttpHost host, HttpHost proxy,
- RequestFeeder requestFeeder) {
- super(context, host, requestFeeder);
- mProxyHost = proxy;
- }
-
- /**
- * Sets the server SSL certificate associated with this
- * connection.
- * @param certificate The SSL certificate
- */
- /* package */ void setCertificate(SslCertificate certificate) {
- mCertificate = certificate;
- }
-
- /**
- * Opens the connection to a http server or proxy.
- *
- * @return the opened low level connection
- * @throws IOException if the connection fails for any reason.
- */
- @Override
- AndroidHttpClientConnection openConnection(Request req) throws IOException {
- SSLSocket sslSock = null;
-
- if (mProxyHost != null) {
- // If we have a proxy set, we first send a CONNECT request
- // to the proxy; if the proxy returns 200 OK, we negotiate
- // a secure connection to the target server via the proxy.
- // If the request fails, we drop it, but provide the event
- // handler with the response status and headers. The event
- // handler is then responsible for cancelling the load or
- // issueing a new request.
- AndroidHttpClientConnection proxyConnection = null;
- Socket proxySock = null;
- try {
- proxySock = new Socket
- (mProxyHost.getHostName(), mProxyHost.getPort());
-
- proxySock.setSoTimeout(60 * 1000);
-
- proxyConnection = new AndroidHttpClientConnection();
- HttpParams params = new BasicHttpParams();
- HttpConnectionParams.setSocketBufferSize(params, 8192);
-
- proxyConnection.bind(proxySock, params);
- } catch(IOException e) {
- if (proxyConnection != null) {
- proxyConnection.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to establish a connection to the proxy";
- }
-
- throw new IOException(errorMessage);
- }
-
- StatusLine statusLine = null;
- int statusCode = 0;
- Headers headers = new Headers();
- try {
- BasicHttpRequest proxyReq = new BasicHttpRequest
- ("CONNECT", mHost.toHostString());
-
- // add all 'proxy' headers from the original request, we also need
- // to add 'host' header unless we want proxy to answer us with a
- // 400 Bad Request
- for (Header h : req.mHttpRequest.getAllHeaders()) {
- String headerName = h.getName().toLowerCase(Locale.ROOT);
- if (headerName.startsWith("proxy") || headerName.equals("keep-alive")
- || headerName.equals("host")) {
- proxyReq.addHeader(h);
- }
- }
-
- proxyConnection.sendRequestHeader(proxyReq);
- proxyConnection.flush();
-
- // it is possible to receive informational status
- // codes prior to receiving actual headers;
- // all those status codes are smaller than OK 200
- // a loop is a standard way of dealing with them
- do {
- statusLine = proxyConnection.parseResponseHeader(headers);
- statusCode = statusLine.getStatusCode();
- } while (statusCode < HttpStatus.SC_OK);
- } catch (ParseException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- } catch (HttpException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- } catch (IOException e) {
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to send a CONNECT request";
- }
-
- throw new IOException(errorMessage);
- }
-
- if (statusCode == HttpStatus.SC_OK) {
- try {
- sslSock = (SSLSocket) getSocketFactory().createSocket(
- proxySock, mHost.getHostName(), mHost.getPort(), true);
- } catch(IOException e) {
- if (sslSock != null) {
- sslSock.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage =
- "failed to create an SSL socket";
- }
- throw new IOException(errorMessage);
- }
- } else {
- // if the code is not OK, inform the event handler
- ProtocolVersion version = statusLine.getProtocolVersion();
-
- req.mEventHandler.status(version.getMajor(),
- version.getMinor(),
- statusCode,
- statusLine.getReasonPhrase());
- req.mEventHandler.headers(headers);
- req.mEventHandler.endData();
-
- proxyConnection.close();
-
- // here, we return null to indicate that the original
- // request needs to be dropped
- return null;
- }
- } else {
- // if we do not have a proxy, we simply connect to the host
- try {
- sslSock = (SSLSocket) getSocketFactory().createSocket(
- mHost.getHostName(), mHost.getPort());
- sslSock.setSoTimeout(SOCKET_TIMEOUT);
- } catch(IOException e) {
- if (sslSock != null) {
- sslSock.close();
- }
-
- String errorMessage = e.getMessage();
- if (errorMessage == null) {
- errorMessage = "failed to create an SSL socket";
- }
-
- throw new IOException(errorMessage);
- }
- }
-
- // do handshake and validate server certificates
- SslError error = CertificateChainValidator.getInstance().
- doHandshakeAndValidateServerCertificates(this, sslSock, mHost.getHostName());
-
- // Inform the user if there is a problem
- if (error != null) {
- // handleSslErrorRequest may immediately unsuspend if it wants to
- // allow the certificate anyway.
- // So we mark the connection as suspended, call handleSslErrorRequest
- // then check if we're still suspended and only wait if we actually
- // need to.
- synchronized (mSuspendLock) {
- mSuspended = true;
- }
- // don't hold the lock while calling out to the event handler
- boolean canHandle = req.getEventHandler().handleSslErrorRequest(error);
- if(!canHandle) {
- throw new IOException("failed to handle "+ error);
- }
- synchronized (mSuspendLock) {
- if (mSuspended) {
- try {
- // Put a limit on how long we are waiting; if the timeout
- // expires (which should never happen unless you choose
- // to ignore the SSL error dialog for a very long time),
- // we wake up the thread and abort the request. This is
- // to prevent us from stalling the network if things go
- // very bad.
- mSuspendLock.wait(10 * 60 * 1000);
- if (mSuspended) {
- // mSuspended is true if we have not had a chance to
- // restart the connection yet (ie, the wait timeout
- // has expired)
- mSuspended = false;
- mAborted = true;
- if (HttpLog.LOGV) {
- HttpLog.v("HttpsConnection.openConnection():" +
- " SSL timeout expired and request was cancelled!!!");
- }
- }
- } catch (InterruptedException e) {
- // ignore
- }
- }
- if (mAborted) {
- // The user decided not to use this unverified connection
- // so close it immediately.
- sslSock.close();
- throw new SSLConnectionClosedByUserException("connection closed by the user");
- }
- }
- }
-
- // All went well, we have an open, verified connection.
- AndroidHttpClientConnection conn = new AndroidHttpClientConnection();
- BasicHttpParams params = new BasicHttpParams();
- params.setIntParameter(HttpConnectionParams.SOCKET_BUFFER_SIZE, 8192);
- conn.bind(sslSock, params);
-
- return conn;
- }
-
- /**
- * Closes the low level connection.
- *
- * If an exception is thrown then it is assumed that the connection will
- * have been closed (to the extent possible) anyway and the caller does not
- * need to take any further action.
- *
- */
- @Override
- void closeConnection() {
- // if the connection has been suspended due to an SSL error
- if (mSuspended) {
- // wake up the network thread
- restartConnection(false);
- }
-
- try {
- if (mHttpClientConnection != null && mHttpClientConnection.isOpen()) {
- mHttpClientConnection.close();
- }
- } catch (IOException e) {
- if (HttpLog.LOGV)
- HttpLog.v("HttpsConnection.closeConnection():" +
- " failed closing connection " + mHost);
- e.printStackTrace();
- }
- }
-
- /**
- * Restart a secure connection suspended waiting for user interaction.
- */
- void restartConnection(boolean proceed) {
- if (HttpLog.LOGV) {
- HttpLog.v("HttpsConnection.restartConnection():" +
- " proceed: " + proceed);
- }
-
- synchronized (mSuspendLock) {
- if (mSuspended) {
- mSuspended = false;
- mAborted = !proceed;
- mSuspendLock.notify();
- }
- }
- }
-
- @Override
- String getScheme() {
- return "https";
- }
-}
-
-/**
- * Simple exception we throw if the SSL connection is closed by the user.
- *
- * {@hide}
- */
-class SSLConnectionClosedByUserException extends SSLException {
-
- public SSLConnectionClosedByUserException(String reason) {
- super(reason);
- }
-}
diff --git a/core/java/android/net/http/IdleCache.java b/core/java/android/net/http/IdleCache.java
deleted file mode 100644
index fda6009..0000000
--- a/core/java/android/net/http/IdleCache.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Hangs onto idle live connections for a little while
- */
-
-package android.net.http;
-
-import org.apache.http.HttpHost;
-
-import android.os.SystemClock;
-
-/**
- * {@hide}
- */
-class IdleCache {
-
- class Entry {
- HttpHost mHost;
- Connection mConnection;
- long mTimeout;
- };
-
- private final static int IDLE_CACHE_MAX = 8;
-
- /* Allow five consecutive empty queue checks before shutdown */
- private final static int EMPTY_CHECK_MAX = 5;
-
- /* six second timeout for connections */
- private final static int TIMEOUT = 6 * 1000;
- private final static int CHECK_INTERVAL = 2 * 1000;
- private Entry[] mEntries = new Entry[IDLE_CACHE_MAX];
-
- private int mCount = 0;
-
- private IdleReaper mThread = null;
-
- /* stats */
- private int mCached = 0;
- private int mReused = 0;
-
- IdleCache() {
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- mEntries[i] = new Entry();
- }
- }
-
- /**
- * Caches connection, if there is room.
- * @return true if connection cached
- */
- synchronized boolean cacheConnection(
- HttpHost host, Connection connection) {
-
- boolean ret = false;
-
- if (HttpLog.LOGV) {
- HttpLog.v("IdleCache size " + mCount + " host " + host);
- }
-
- if (mCount < IDLE_CACHE_MAX) {
- long time = SystemClock.uptimeMillis();
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost == null) {
- entry.mHost = host;
- entry.mConnection = connection;
- entry.mTimeout = time + TIMEOUT;
- mCount++;
- if (HttpLog.LOGV) mCached++;
- ret = true;
- if (mThread == null) {
- mThread = new IdleReaper();
- mThread.start();
- }
- break;
- }
- }
- }
- return ret;
- }
-
- synchronized Connection getConnection(HttpHost host) {
- Connection ret = null;
-
- if (mCount > 0) {
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- HttpHost eHost = entry.mHost;
- if (eHost != null && eHost.equals(host)) {
- ret = entry.mConnection;
- entry.mHost = null;
- entry.mConnection = null;
- mCount--;
- if (HttpLog.LOGV) mReused++;
- break;
- }
- }
- }
- return ret;
- }
-
- synchronized void clear() {
- for (int i = 0; mCount > 0 && i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost != null) {
- entry.mHost = null;
- entry.mConnection.closeConnection();
- entry.mConnection = null;
- mCount--;
- }
- }
- }
-
- private synchronized void clearIdle() {
- if (mCount > 0) {
- long time = SystemClock.uptimeMillis();
- for (int i = 0; i < IDLE_CACHE_MAX; i++) {
- Entry entry = mEntries[i];
- if (entry.mHost != null && time > entry.mTimeout) {
- entry.mHost = null;
- entry.mConnection.closeConnection();
- entry.mConnection = null;
- mCount--;
- }
- }
- }
- }
-
- private class IdleReaper extends Thread {
-
- public void run() {
- int check = 0;
-
- setName("IdleReaper");
- android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
- synchronized (IdleCache.this) {
- while (check < EMPTY_CHECK_MAX) {
- try {
- IdleCache.this.wait(CHECK_INTERVAL);
- } catch (InterruptedException ex) {
- }
- if (mCount == 0) {
- check++;
- } else {
- check = 0;
- clearIdle();
- }
- }
- mThread = null;
- }
- if (HttpLog.LOGV) {
- HttpLog.v("IdleCache IdleReaper shutdown: cached " + mCached +
- " reused " + mReused);
- mCached = 0;
- mReused = 0;
- }
- }
- }
-}
diff --git a/core/java/android/net/http/LoggingEventHandler.java b/core/java/android/net/http/LoggingEventHandler.java
deleted file mode 100644
index bdafa0b..0000000
--- a/core/java/android/net/http/LoggingEventHandler.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * A test EventHandler: Logs everything received
- */
-
-package android.net.http;
-
-import android.net.http.Headers;
-
-/**
- * {@hide}
- */
-public class LoggingEventHandler implements EventHandler {
-
- public void requestSent() {
- HttpLog.v("LoggingEventHandler:requestSent()");
- }
-
- public void status(int major_version,
- int minor_version,
- int code, /* Status-Code value */
- String reason_phrase) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler:status() major: " + major_version +
- " minor: " + minor_version +
- " code: " + code +
- " reason: " + reason_phrase);
- }
- }
-
- public void headers(Headers headers) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler:headers()");
- HttpLog.v(headers.toString());
- }
- }
-
- public void locationChanged(String newLocation, boolean permanent) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: locationChanged() " + newLocation +
- " permanent " + permanent);
- }
- }
-
- public void data(byte[] data, int len) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: data() " + len + " bytes");
- }
- // HttpLog.v(new String(data, 0, len));
- }
- public void endData() {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: endData() called");
- }
- }
-
- public void certificate(SslCertificate certificate) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: certificate(): " + certificate);
- }
- }
-
- public void error(int id, String description) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: error() called Id:" + id +
- " description " + description);
- }
- }
-
- public boolean handleSslErrorRequest(SslError error) {
- if (HttpLog.LOGV) {
- HttpLog.v("LoggingEventHandler: handleSslErrorRequest():" + error);
- }
- // return false so that the caller thread won't wait forever
- return false;
- }
-}
diff --git a/core/java/android/net/http/Request.java b/core/java/android/net/http/Request.java
deleted file mode 100644
index 76d7bb9..0000000
--- a/core/java/android/net/http/Request.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.http.entity.InputStreamEntity;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpEntityEnclosingRequest;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpStatus;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolVersion;
-
-import org.apache.http.StatusLine;
-import org.apache.http.message.BasicHttpRequest;
-import org.apache.http.message.BasicHttpEntityEnclosingRequest;
-import org.apache.http.protocol.RequestContent;
-
-/**
- * Represents an HTTP request for a given host.
- *
- * {@hide}
- */
-
-class Request {
-
- /** The eventhandler to call as the request progresses */
- EventHandler mEventHandler;
-
- private Connection mConnection;
-
- /** The Apache http request */
- BasicHttpRequest mHttpRequest;
-
- /** The path component of this request */
- String mPath;
-
- /** Host serving this request */
- HttpHost mHost;
-
- /** Set if I'm using a proxy server */
- HttpHost mProxyHost;
-
- /** True if request has been cancelled */
- volatile boolean mCancelled = false;
-
- int mFailCount = 0;
-
- // This will be used to set the Range field if we retry a connection. This
- // is http/1.1 feature.
- private int mReceivedBytes = 0;
-
- private InputStream mBodyProvider;
- private int mBodyLength;
-
- private final static String HOST_HEADER = "Host";
- private final static String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
- private final static String CONTENT_LENGTH_HEADER = "content-length";
-
- /* Used to synchronize waitUntilComplete() requests */
- private final Object mClientResource = new Object();
-
- /** True if loading should be paused **/
- private boolean mLoadingPaused = false;
-
- /**
- * Processor used to set content-length and transfer-encoding
- * headers.
- */
- private static RequestContent requestContentProcessor =
- new RequestContent();
-
- /**
- * Instantiates a new Request.
- * @param method GET/POST/PUT
- * @param host The server that will handle this request
- * @param path path part of URI
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- * @param eventHandler request will make progress callbacks on
- * this interface
- * @param headers reqeust headers
- */
- Request(String method, HttpHost host, HttpHost proxyHost, String path,
- InputStream bodyProvider, int bodyLength,
- EventHandler eventHandler,
- Map<String, String> headers) {
- mEventHandler = eventHandler;
- mHost = host;
- mProxyHost = proxyHost;
- mPath = path;
- mBodyProvider = bodyProvider;
- mBodyLength = bodyLength;
-
- if (bodyProvider == null && !"POST".equalsIgnoreCase(method)) {
- mHttpRequest = new BasicHttpRequest(method, getUri());
- } else {
- mHttpRequest = new BasicHttpEntityEnclosingRequest(
- method, getUri());
- // it is ok to have null entity for BasicHttpEntityEnclosingRequest.
- // By using BasicHttpEntityEnclosingRequest, it will set up the
- // correct content-length, content-type and content-encoding.
- if (bodyProvider != null) {
- setBodyProvider(bodyProvider, bodyLength);
- }
- }
- addHeader(HOST_HEADER, getHostPort());
-
- /* FIXME: if webcore will make the root document a
- high-priority request, we can ask for gzip encoding only on
- high priority reqs (saving the trouble for images, etc) */
- addHeader(ACCEPT_ENCODING_HEADER, "gzip");
- addHeaders(headers);
- }
-
- /**
- * @param pause True if the load should be paused.
- */
- synchronized void setLoadingPaused(boolean pause) {
- mLoadingPaused = pause;
-
- // Wake up the paused thread if we're unpausing the load.
- if (!mLoadingPaused) {
- notify();
- }
- }
-
- /**
- * @param connection Request served by this connection
- */
- void setConnection(Connection connection) {
- mConnection = connection;
- }
-
- /* package */ EventHandler getEventHandler() {
- return mEventHandler;
- }
-
- /**
- * Add header represented by given pair to request. Header will
- * be formatted in request as "name: value\r\n".
- * @param name of header
- * @param value of header
- */
- void addHeader(String name, String value) {
- if (name == null) {
- String damage = "Null http header name";
- HttpLog.e(damage);
- throw new NullPointerException(damage);
- }
- if (value == null || value.length() == 0) {
- String damage = "Null or empty value for header \"" + name + "\"";
- HttpLog.e(damage);
- throw new RuntimeException(damage);
- }
- mHttpRequest.addHeader(name, value);
- }
-
- /**
- * Add all headers in given map to this request. This is a helper
- * method: it calls addHeader for each pair in the map.
- */
- void addHeaders(Map<String, String> headers) {
- if (headers == null) {
- return;
- }
-
- Entry<String, String> entry;
- Iterator<Entry<String, String>> i = headers.entrySet().iterator();
- while (i.hasNext()) {
- entry = i.next();
- addHeader(entry.getKey(), entry.getValue());
- }
- }
-
- /**
- * Send the request line and headers
- */
- void sendRequest(AndroidHttpClientConnection httpClientConnection)
- throws HttpException, IOException {
-
- if (mCancelled) return; // don't send cancelled requests
-
- if (HttpLog.LOGV) {
- HttpLog.v("Request.sendRequest() " + mHost.getSchemeName() + "://" + getHostPort());
- // HttpLog.v(mHttpRequest.getRequestLine().toString());
- if (false) {
- Iterator i = mHttpRequest.headerIterator();
- while (i.hasNext()) {
- Header header = (Header)i.next();
- HttpLog.v(header.getName() + ": " + header.getValue());
- }
- }
- }
-
- requestContentProcessor.process(mHttpRequest,
- mConnection.getHttpContext());
- httpClientConnection.sendRequestHeader(mHttpRequest);
- if (mHttpRequest instanceof HttpEntityEnclosingRequest) {
- httpClientConnection.sendRequestEntity(
- (HttpEntityEnclosingRequest) mHttpRequest);
- }
-
- if (HttpLog.LOGV) {
- HttpLog.v("Request.requestSent() " + mHost.getSchemeName() + "://" + getHostPort() + mPath);
- }
- }
-
-
- /**
- * Receive a single http response.
- *
- * @param httpClientConnection the request to receive the response for.
- */
- void readResponse(AndroidHttpClientConnection httpClientConnection)
- throws IOException, ParseException {
-
- if (mCancelled) return; // don't send cancelled requests
-
- StatusLine statusLine = null;
- boolean hasBody = false;
- httpClientConnection.flush();
- int statusCode = 0;
-
- Headers header = new Headers();
- do {
- statusLine = httpClientConnection.parseResponseHeader(header);
- statusCode = statusLine.getStatusCode();
- } while (statusCode < HttpStatus.SC_OK);
- if (HttpLog.LOGV) HttpLog.v(
- "Request.readResponseStatus() " +
- statusLine.toString().length() + " " + statusLine);
-
- ProtocolVersion v = statusLine.getProtocolVersion();
- mEventHandler.status(v.getMajor(), v.getMinor(),
- statusCode, statusLine.getReasonPhrase());
- mEventHandler.headers(header);
- HttpEntity entity = null;
- hasBody = canResponseHaveBody(mHttpRequest, statusCode);
-
- if (hasBody)
- entity = httpClientConnection.receiveResponseEntity(header);
-
- // restrict the range request to the servers claiming that they are
- // accepting ranges in bytes
- boolean supportPartialContent = "bytes".equalsIgnoreCase(header
- .getAcceptRanges());
-
- if (entity != null) {
- InputStream is = entity.getContent();
-
- // process gzip content encoding
- Header contentEncoding = entity.getContentEncoding();
- InputStream nis = null;
- byte[] buf = null;
- int count = 0;
- try {
- if (contentEncoding != null &&
- contentEncoding.getValue().equals("gzip")) {
- nis = new GZIPInputStream(is);
- } else {
- nis = is;
- }
-
- /* accumulate enough data to make it worth pushing it
- * up the stack */
- buf = mConnection.getBuf();
- int len = 0;
- int lowWater = buf.length / 2;
- while (len != -1) {
- synchronized(this) {
- while (mLoadingPaused) {
- // Put this (network loading) thread to sleep if WebCore
- // has asked us to. This can happen with plugins for
- // example, if we are streaming data but the plugin has
- // filled its internal buffers.
- try {
- wait();
- } catch (InterruptedException e) {
- HttpLog.e("Interrupted exception whilst "
- + "network thread paused at WebCore's request."
- + " " + e.getMessage());
- }
- }
- }
-
- len = nis.read(buf, count, buf.length - count);
-
- if (len != -1) {
- count += len;
- if (supportPartialContent) mReceivedBytes += len;
- }
- if (len == -1 || count >= lowWater) {
- if (HttpLog.LOGV) HttpLog.v("Request.readResponse() " + count);
- mEventHandler.data(buf, count);
- count = 0;
- }
- }
- } catch (EOFException e) {
- /* InflaterInputStream throws an EOFException when the
- server truncates gzipped content. Handle this case
- as we do truncated non-gzipped content: no error */
- if (count > 0) {
- // if there is uncommited content, we should commit them
- mEventHandler.data(buf, count);
- }
- if (HttpLog.LOGV) HttpLog.v( "readResponse() handling " + e);
- } catch(IOException e) {
- // don't throw if we have a non-OK status code
- if (statusCode == HttpStatus.SC_OK
- || statusCode == HttpStatus.SC_PARTIAL_CONTENT) {
- if (supportPartialContent && count > 0) {
- // if there is uncommited content, we should commit them
- // as we will continue the request
- mEventHandler.data(buf, count);
- }
- throw e;
- }
- } finally {
- if (nis != null) {
- nis.close();
- }
- }
- }
- mConnection.setCanPersist(entity, statusLine.getProtocolVersion(),
- header.getConnectionType());
- mEventHandler.endData();
- complete();
-
- if (HttpLog.LOGV) HttpLog.v("Request.readResponse(): done " +
- mHost.getSchemeName() + "://" + getHostPort() + mPath);
- }
-
- /**
- * Data will not be sent to or received from server after cancel()
- * call. Does not close connection--use close() below for that.
- *
- * Called by RequestHandle from non-network thread
- */
- synchronized void cancel() {
- if (HttpLog.LOGV) {
- HttpLog.v("Request.cancel(): " + getUri());
- }
-
- // Ensure that the network thread is not blocked by a hanging request from WebCore to
- // pause the load.
- mLoadingPaused = false;
- notify();
-
- mCancelled = true;
- if (mConnection != null) {
- mConnection.cancel();
- }
- }
-
- String getHostPort() {
- String myScheme = mHost.getSchemeName();
- int myPort = mHost.getPort();
-
- // Only send port when we must... many servers can't deal with it
- if (myPort != 80 && myScheme.equals("http") ||
- myPort != 443 && myScheme.equals("https")) {
- return mHost.toHostString();
- } else {
- return mHost.getHostName();
- }
- }
-
- String getUri() {
- if (mProxyHost == null ||
- mHost.getSchemeName().equals("https")) {
- return mPath;
- }
- return mHost.getSchemeName() + "://" + getHostPort() + mPath;
- }
-
- /**
- * for debugging
- */
- public String toString() {
- return mPath;
- }
-
-
- /**
- * If this request has been sent once and failed, it must be reset
- * before it can be sent again.
- */
- void reset() {
- /* clear content-length header */
- mHttpRequest.removeHeaders(CONTENT_LENGTH_HEADER);
-
- if (mBodyProvider != null) {
- try {
- mBodyProvider.reset();
- } catch (IOException ex) {
- if (HttpLog.LOGV) HttpLog.v(
- "failed to reset body provider " +
- getUri());
- }
- setBodyProvider(mBodyProvider, mBodyLength);
- }
-
- if (mReceivedBytes > 0) {
- // reset the fail count as we continue the request
- mFailCount = 0;
- // set the "Range" header to indicate that the retry will continue
- // instead of restarting the request
- HttpLog.v("*** Request.reset() to range:" + mReceivedBytes);
- mHttpRequest.setHeader("Range", "bytes=" + mReceivedBytes + "-");
- }
- }
-
- /**
- * Pause thread request completes. Used for synchronous requests,
- * and testing
- */
- void waitUntilComplete() {
- synchronized (mClientResource) {
- try {
- if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete()");
- mClientResource.wait();
- if (HttpLog.LOGV) HttpLog.v("Request.waitUntilComplete() done waiting");
- } catch (InterruptedException e) {
- }
- }
- }
-
- void complete() {
- synchronized (mClientResource) {
- mClientResource.notifyAll();
- }
- }
-
- /**
- * Decide whether a response comes with an entity.
- * The implementation in this class is based on RFC 2616.
- * Unknown methods and response codes are supposed to
- * indicate responses with an entity.
- * <br/>
- * Derived executors can override this method to handle
- * methods and response codes not specified in RFC 2616.
- *
- * @param request the request, to obtain the executed method
- * @param response the response, to obtain the status code
- */
-
- private static boolean canResponseHaveBody(final HttpRequest request,
- final int status) {
-
- if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
- return false;
- }
- return status >= HttpStatus.SC_OK
- && status != HttpStatus.SC_NO_CONTENT
- && status != HttpStatus.SC_NOT_MODIFIED;
- }
-
- /**
- * Supply an InputStream that provides the body of a request. It's
- * not great that the caller must also provide the length of the data
- * returned by that InputStream, but the client needs to know up
- * front, and I'm not sure how to get this out of the InputStream
- * itself without a costly readthrough. I'm not sure skip() would
- * do what we want. If you know a better way, please let me know.
- */
- private void setBodyProvider(InputStream bodyProvider, int bodyLength) {
- if (!bodyProvider.markSupported()) {
- throw new IllegalArgumentException(
- "bodyProvider must support mark()");
- }
- // Mark beginning of stream
- bodyProvider.mark(Integer.MAX_VALUE);
-
- ((BasicHttpEntityEnclosingRequest)mHttpRequest).setEntity(
- new InputStreamEntity(bodyProvider, bodyLength));
- }
-
-
- /**
- * Handles SSL error(s) on the way down from the user (the user
- * has already provided their feedback).
- */
- public void handleSslErrorResponse(boolean proceed) {
- HttpsConnection connection = (HttpsConnection)(mConnection);
- if (connection != null) {
- connection.restartConnection(proceed);
- }
- }
-
- /**
- * Helper: calls error() on eventhandler with appropriate message
- * This should not be called before the mConnection is set.
- */
- void error(int errorId, int resourceId) {
- mEventHandler.error(
- errorId,
- mConnection.mContext.getText(
- resourceId).toString());
- }
-
-}
diff --git a/core/java/android/net/http/RequestFeeder.java b/core/java/android/net/http/RequestFeeder.java
deleted file mode 100644
index 34ca267..0000000
--- a/core/java/android/net/http/RequestFeeder.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Supplies Requests to a Connection
- */
-
-package android.net.http;
-
-import org.apache.http.HttpHost;
-
-/**
- * {@hide}
- */
-interface RequestFeeder {
-
- Request getRequest();
- Request getRequest(HttpHost host);
-
- /**
- * @return true if a request for this host is available
- */
- boolean haveRequest(HttpHost host);
-
- /**
- * Put request back on head of queue
- */
- void requeueRequest(Request request);
-}
diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java
deleted file mode 100644
index f23f69c..0000000
--- a/core/java/android/net/http/RequestHandle.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.http;
-
-import android.net.ParseException;
-import android.net.WebAddress;
-import junit.framework.Assert;
-import android.webkit.CookieManager;
-
-import org.apache.commons.codec.binary.Base64;
-
-import java.io.InputStream;
-import java.lang.Math;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Random;
-
-/**
- * RequestHandle: handles a request session that may include multiple
- * redirects, HTTP authentication requests, etc.
- *
- * {@hide}
- */
-public class RequestHandle {
-
- private String mUrl;
- private WebAddress mUri;
- private String mMethod;
- private Map<String, String> mHeaders;
- private RequestQueue mRequestQueue;
- private Request mRequest;
- private InputStream mBodyProvider;
- private int mBodyLength;
- private int mRedirectCount = 0;
- // Used only with synchronous requests.
- private Connection mConnection;
-
- private final static String AUTHORIZATION_HEADER = "Authorization";
- private final static String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";
-
- public final static int MAX_REDIRECT_COUNT = 16;
-
- /**
- * Creates a new request session.
- */
- public RequestHandle(RequestQueue requestQueue, String url, WebAddress uri,
- String method, Map<String, String> headers,
- InputStream bodyProvider, int bodyLength, Request request) {
-
- if (headers == null) {
- headers = new HashMap<String, String>();
- }
- mHeaders = headers;
- mBodyProvider = bodyProvider;
- mBodyLength = bodyLength;
- mMethod = method == null? "GET" : method;
-
- mUrl = url;
- mUri = uri;
-
- mRequestQueue = requestQueue;
-
- mRequest = request;
- }
-
- /**
- * Creates a new request session with a given Connection. This connection
- * is used during a synchronous load to handle this request.
- */
- public RequestHandle(RequestQueue requestQueue, String url, WebAddress uri,
- String method, Map<String, String> headers,
- InputStream bodyProvider, int bodyLength, Request request,
- Connection conn) {
- this(requestQueue, url, uri, method, headers, bodyProvider, bodyLength,
- request);
- mConnection = conn;
- }
-
- /**
- * Cancels this request
- */
- public void cancel() {
- if (mRequest != null) {
- mRequest.cancel();
- }
- }
-
- /**
- * Pauses the loading of this request. For example, called from the WebCore thread
- * when the plugin can take no more data.
- */
- public void pauseRequest(boolean pause) {
- if (mRequest != null) {
- mRequest.setLoadingPaused(pause);
- }
- }
-
- /**
- * Handles SSL error(s) on the way down from the user (the user
- * has already provided their feedback).
- */
- public void handleSslErrorResponse(boolean proceed) {
- if (mRequest != null) {
- mRequest.handleSslErrorResponse(proceed);
- }
- }
-
- /**
- * @return true if we've hit the max redirect count
- */
- public boolean isRedirectMax() {
- return mRedirectCount >= MAX_REDIRECT_COUNT;
- }
-
- public int getRedirectCount() {
- return mRedirectCount;
- }
-
- public void setRedirectCount(int count) {
- mRedirectCount = count;
- }
-
- /**
- * Create and queue a redirect request.
- *
- * @param redirectTo URL to redirect to
- * @param statusCode HTTP status code returned from original request
- * @param cacheHeaders Cache header for redirect URL
- * @return true if setup succeeds, false otherwise (redirect loop
- * count exceeded, body provider unable to rewind on 307 redirect)
- */
- public boolean setupRedirect(String redirectTo, int statusCode,
- Map<String, String> cacheHeaders) {
- if (HttpLog.LOGV) {
- HttpLog.v("RequestHandle.setupRedirect(): redirectCount " +
- mRedirectCount);
- }
-
- // be careful and remove authentication headers, if any
- mHeaders.remove(AUTHORIZATION_HEADER);
- mHeaders.remove(PROXY_AUTHORIZATION_HEADER);
-
- if (++mRedirectCount == MAX_REDIRECT_COUNT) {
- // Way too many redirects -- fail out
- if (HttpLog.LOGV) HttpLog.v(
- "RequestHandle.setupRedirect(): too many redirects " +
- mRequest);
- mRequest.error(EventHandler.ERROR_REDIRECT_LOOP,
- com.android.internal.R.string.httpErrorRedirectLoop);
- return false;
- }
-
- if (mUrl.startsWith("https:") && redirectTo.startsWith("http:")) {
- // implement http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
- if (HttpLog.LOGV) {
- HttpLog.v("blowing away the referer on an https -> http redirect");
- }
- mHeaders.remove("Referer");
- }
-
- mUrl = redirectTo;
- try {
- mUri = new WebAddress(mUrl);
- } catch (ParseException e) {
- e.printStackTrace();
- }
-
- // update the "Cookie" header based on the redirected url
- mHeaders.remove("Cookie");
- String cookie = CookieManager.getInstance().getCookie(mUri);
- if (cookie != null && cookie.length() > 0) {
- mHeaders.put("Cookie", cookie);
- }
-
- if ((statusCode == 302 || statusCode == 303) && mMethod.equals("POST")) {
- if (HttpLog.LOGV) {
- HttpLog.v("replacing POST with GET on redirect to " + redirectTo);
- }
- mMethod = "GET";
- }
- /* Only repost content on a 307. If 307, reset the body
- provider so we can replay the body */
- if (statusCode == 307) {
- try {
- if (mBodyProvider != null) mBodyProvider.reset();
- } catch (java.io.IOException ex) {
- if (HttpLog.LOGV) {
- HttpLog.v("setupRedirect() failed to reset body provider");
- }
- return false;
- }
-
- } else {
- mHeaders.remove("Content-Type");
- mBodyProvider = null;
- }
-
- // Update the cache headers for this URL
- mHeaders.putAll(cacheHeaders);
-
- createAndQueueNewRequest();
- return true;
- }
-
- /**
- * Create and queue an HTTP authentication-response (basic) request.
- */
- public void setupBasicAuthResponse(boolean isProxy, String username, String password) {
- String response = computeBasicAuthResponse(username, password);
- if (HttpLog.LOGV) {
- HttpLog.v("setupBasicAuthResponse(): response: " + response);
- }
- mHeaders.put(authorizationHeader(isProxy), "Basic " + response);
- setupAuthResponse();
- }
-
- /**
- * Create and queue an HTTP authentication-response (digest) request.
- */
- public void setupDigestAuthResponse(boolean isProxy,
- String username,
- String password,
- String realm,
- String nonce,
- String QOP,
- String algorithm,
- String opaque) {
-
- String response = computeDigestAuthResponse(
- username, password, realm, nonce, QOP, algorithm, opaque);
- if (HttpLog.LOGV) {
- HttpLog.v("setupDigestAuthResponse(): response: " + response);
- }
- mHeaders.put(authorizationHeader(isProxy), "Digest " + response);
- setupAuthResponse();
- }
-
- private void setupAuthResponse() {
- try {
- if (mBodyProvider != null) mBodyProvider.reset();
- } catch (java.io.IOException ex) {
- if (HttpLog.LOGV) {
- HttpLog.v("setupAuthResponse() failed to reset body provider");
- }
- }
- createAndQueueNewRequest();
- }
-
- /**
- * @return HTTP request method (GET, PUT, etc).
- */
- public String getMethod() {
- return mMethod;
- }
-
- /**
- * @return Basic-scheme authentication response: BASE64(username:password).
- */
- public static String computeBasicAuthResponse(String username, String password) {
- Assert.assertNotNull(username);
- Assert.assertNotNull(password);
-
- // encode username:password to base64
- return new String(Base64.encodeBase64((username + ':' + password).getBytes()));
- }
-
- public void waitUntilComplete() {
- mRequest.waitUntilComplete();
- }
-
- public void processRequest() {
- if (mConnection != null) {
- mConnection.processRequests(mRequest);
- }
- }
-
- /**
- * @return Digest-scheme authentication response.
- */
- private String computeDigestAuthResponse(String username,
- String password,
- String realm,
- String nonce,
- String QOP,
- String algorithm,
- String opaque) {
-
- Assert.assertNotNull(username);
- Assert.assertNotNull(password);
- Assert.assertNotNull(realm);
-
- String A1 = username + ":" + realm + ":" + password;
- String A2 = mMethod + ":" + mUrl;
-
- // because we do not preemptively send authorization headers, nc is always 1
- String nc = "00000001";
- String cnonce = computeCnonce();
- String digest = computeDigest(A1, A2, nonce, QOP, nc, cnonce);
-
- String response = "";
- response += "username=" + doubleQuote(username) + ", ";
- response += "realm=" + doubleQuote(realm) + ", ";
- response += "nonce=" + doubleQuote(nonce) + ", ";
- response += "uri=" + doubleQuote(mUrl) + ", ";
- response += "response=" + doubleQuote(digest) ;
-
- if (opaque != null) {
- response += ", opaque=" + doubleQuote(opaque);
- }
-
- if (algorithm != null) {
- response += ", algorithm=" + algorithm;
- }
-
- if (QOP != null) {
- response += ", qop=" + QOP + ", nc=" + nc + ", cnonce=" + doubleQuote(cnonce);
- }
-
- return response;
- }
-
- /**
- * @return The right authorization header (dependeing on whether it is a proxy or not).
- */
- public static String authorizationHeader(boolean isProxy) {
- if (!isProxy) {
- return AUTHORIZATION_HEADER;
- } else {
- return PROXY_AUTHORIZATION_HEADER;
- }
- }
-
- /**
- * @return Double-quoted MD5 digest.
- */
- private String computeDigest(
- String A1, String A2, String nonce, String QOP, String nc, String cnonce) {
- if (HttpLog.LOGV) {
- HttpLog.v("computeDigest(): QOP: " + QOP);
- }
-
- if (QOP == null) {
- return KD(H(A1), nonce + ":" + H(A2));
- } else {
- if (QOP.equalsIgnoreCase("auth")) {
- return KD(H(A1), nonce + ":" + nc + ":" + cnonce + ":" + QOP + ":" + H(A2));
- }
- }
-
- return null;
- }
-
- /**
- * @return MD5 hash of concat(secret, ":", data).
- */
- private String KD(String secret, String data) {
- return H(secret + ":" + data);
- }
-
- /**
- * @return MD5 hash of param.
- */
- private String H(String param) {
- if (param != null) {
- try {
- MessageDigest md5 = MessageDigest.getInstance("MD5");
-
- byte[] d = md5.digest(param.getBytes());
- if (d != null) {
- return bufferToHex(d);
- }
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
- }
- }
-
- return null;
- }
-
- /**
- * @return HEX buffer representation.
- */
- private String bufferToHex(byte[] buffer) {
- final char hexChars[] =
- { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
-
- if (buffer != null) {
- int length = buffer.length;
- if (length > 0) {
- StringBuilder hex = new StringBuilder(2 * length);
-
- for (int i = 0; i < length; ++i) {
- byte l = (byte) (buffer[i] & 0x0F);
- byte h = (byte)((buffer[i] & 0xF0) >> 4);
-
- hex.append(hexChars[h]);
- hex.append(hexChars[l]);
- }
-
- return hex.toString();
- } else {
- return "";
- }
- }
-
- return null;
- }
-
- /**
- * Computes a random cnonce value based on the current time.
- */
- private String computeCnonce() {
- Random rand = new Random();
- int nextInt = rand.nextInt();
- nextInt = (nextInt == Integer.MIN_VALUE) ?
- Integer.MAX_VALUE : Math.abs(nextInt);
- return Integer.toString(nextInt, 16);
- }
-
- /**
- * "Double-quotes" the argument.
- */
- private String doubleQuote(String param) {
- if (param != null) {
- return "\"" + param + "\"";
- }
-
- return null;
- }
-
- /**
- * Creates and queues new request.
- */
- private void createAndQueueNewRequest() {
- // mConnection is non-null if and only if the requests are synchronous.
- if (mConnection != null) {
- RequestHandle newHandle = mRequestQueue.queueSynchronousRequest(
- mUrl, mUri, mMethod, mHeaders, mRequest.mEventHandler,
- mBodyProvider, mBodyLength);
- mRequest = newHandle.mRequest;
- mConnection = newHandle.mConnection;
- newHandle.processRequest();
- return;
- }
- mRequest = mRequestQueue.queueRequest(
- mUrl, mUri, mMethod, mHeaders, mRequest.mEventHandler,
- mBodyProvider,
- mBodyLength).mRequest;
- }
-}
diff --git a/core/java/android/net/http/RequestQueue.java b/core/java/android/net/http/RequestQueue.java
deleted file mode 100644
index 7d2da1b..0000000
--- a/core/java/android/net/http/RequestQueue.java
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * High level HTTP Interface
- * Queues requests as necessary
- */
-
-package android.net.http;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.Proxy;
-import android.net.WebAddress;
-import android.util.Log;
-
-import java.io.InputStream;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.apache.http.HttpHost;
-
-/**
- * {@hide}
- */
-public class RequestQueue implements RequestFeeder {
-
-
- /**
- * Requests, indexed by HttpHost (scheme, host, port)
- */
- private final LinkedHashMap<HttpHost, LinkedList<Request>> mPending;
- private final Context mContext;
- private final ActivePool mActivePool;
- private final ConnectivityManager mConnectivityManager;
-
- private HttpHost mProxyHost = null;
- private BroadcastReceiver mProxyChangeReceiver;
-
- /* default simultaneous connection count */
- private static final int CONNECTION_COUNT = 4;
-
- /**
- * This class maintains active connection threads
- */
- class ActivePool implements ConnectionManager {
- /** Threads used to process requests */
- ConnectionThread[] mThreads;
-
- IdleCache mIdleCache;
-
- private int mTotalRequest;
- private int mTotalConnection;
- private int mConnectionCount;
-
- ActivePool(int connectionCount) {
- mIdleCache = new IdleCache();
- mConnectionCount = connectionCount;
- mThreads = new ConnectionThread[mConnectionCount];
-
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i] = new ConnectionThread(
- mContext, i, this, RequestQueue.this);
- }
- }
-
- void startup() {
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i].start();
- }
- }
-
- void shutdown() {
- for (int i = 0; i < mConnectionCount; i++) {
- mThreads[i].requestStop();
- }
- }
-
- void startConnectionThread() {
- synchronized (RequestQueue.this) {
- RequestQueue.this.notify();
- }
- }
-
- public void startTiming() {
- for (int i = 0; i < mConnectionCount; i++) {
- ConnectionThread rt = mThreads[i];
- rt.mCurrentThreadTime = -1;
- rt.mTotalThreadTime = 0;
- }
- mTotalRequest = 0;
- mTotalConnection = 0;
- }
-
- public void stopTiming() {
- int totalTime = 0;
- for (int i = 0; i < mConnectionCount; i++) {
- ConnectionThread rt = mThreads[i];
- if (rt.mCurrentThreadTime != -1) {
- totalTime += rt.mTotalThreadTime;
- }
- rt.mCurrentThreadTime = 0;
- }
- Log.d("Http", "Http thread used " + totalTime + " ms " + " for "
- + mTotalRequest + " requests and " + mTotalConnection
- + " new connections");
- }
-
- void logState() {
- StringBuilder dump = new StringBuilder();
- for (int i = 0; i < mConnectionCount; i++) {
- dump.append(mThreads[i] + "\n");
- }
- HttpLog.v(dump.toString());
- }
-
-
- public HttpHost getProxyHost() {
- return mProxyHost;
- }
-
- /**
- * Turns off persistence on all live connections
- */
- void disablePersistence() {
- for (int i = 0; i < mConnectionCount; i++) {
- Connection connection = mThreads[i].mConnection;
- if (connection != null) connection.setCanPersist(false);
- }
- mIdleCache.clear();
- }
-
- /* Linear lookup -- okay for small thread counts. Might use
- private HashMap<HttpHost, LinkedList<ConnectionThread>> mActiveMap;
- if this turns out to be a hotspot */
- ConnectionThread getThread(HttpHost host) {
- synchronized(RequestQueue.this) {
- for (int i = 0; i < mThreads.length; i++) {
- ConnectionThread ct = mThreads[i];
- Connection connection = ct.mConnection;
- if (connection != null && connection.mHost.equals(host)) {
- return ct;
- }
- }
- }
- return null;
- }
-
- public Connection getConnection(Context context, HttpHost host) {
- host = RequestQueue.this.determineHost(host);
- Connection con = mIdleCache.getConnection(host);
- if (con == null) {
- mTotalConnection++;
- con = Connection.getConnection(mContext, host, mProxyHost,
- RequestQueue.this);
- }
- return con;
- }
- public boolean recycleConnection(Connection connection) {
- return mIdleCache.cacheConnection(connection.getHost(), connection);
- }
-
- }
-
- /**
- * A RequestQueue class instance maintains a set of queued
- * requests. It orders them, makes the requests against HTTP
- * servers, and makes callbacks to supplied eventHandlers as data
- * is read. It supports request prioritization, connection reuse
- * and pipelining.
- *
- * @param context application context
- */
- public RequestQueue(Context context) {
- this(context, CONNECTION_COUNT);
- }
-
- /**
- * A RequestQueue class instance maintains a set of queued
- * requests. It orders them, makes the requests against HTTP
- * servers, and makes callbacks to supplied eventHandlers as data
- * is read. It supports request prioritization, connection reuse
- * and pipelining.
- *
- * @param context application context
- * @param connectionCount The number of simultaneous connections
- */
- public RequestQueue(Context context, int connectionCount) {
- mContext = context;
-
- mPending = new LinkedHashMap<HttpHost, LinkedList<Request>>(32);
-
- mActivePool = new ActivePool(connectionCount);
- mActivePool.startup();
-
- mConnectivityManager = (ConnectivityManager)
- context.getSystemService(Context.CONNECTIVITY_SERVICE);
- }
-
- /**
- * Enables data state and proxy tracking
- */
- public synchronized void enablePlatformNotifications() {
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.enablePlatformNotifications() network");
-
- if (mProxyChangeReceiver == null) {
- mProxyChangeReceiver =
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context ctx, Intent intent) {
- setProxyConfig();
- }
- };
- mContext.registerReceiver(mProxyChangeReceiver,
- new IntentFilter(Proxy.PROXY_CHANGE_ACTION));
- }
- // we need to resample the current proxy setup
- setProxyConfig();
- }
-
- /**
- * If platform notifications have been enabled, call this method
- * to disable before destroying RequestQueue
- */
- public synchronized void disablePlatformNotifications() {
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.disablePlatformNotifications() network");
-
- if (mProxyChangeReceiver != null) {
- mContext.unregisterReceiver(mProxyChangeReceiver);
- mProxyChangeReceiver = null;
- }
- }
-
- /**
- * Because our IntentReceiver can run within a different thread,
- * synchronize setting the proxy
- */
- private synchronized void setProxyConfig() {
- NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
- if (info != null && info.getType() == ConnectivityManager.TYPE_WIFI) {
- mProxyHost = null;
- } else {
- String host = Proxy.getHost(mContext);
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.setProxyConfig " + host);
- if (host == null) {
- mProxyHost = null;
- } else {
- mActivePool.disablePersistence();
- mProxyHost = new HttpHost(host, Proxy.getPort(mContext), "http");
- }
- }
- }
-
- /**
- * used by webkit
- * @return proxy host if set, null otherwise
- */
- public HttpHost getProxyHost() {
- return mProxyHost;
- }
-
- /**
- * Queues an HTTP request
- * @param url The url to load.
- * @param method "GET" or "POST."
- * @param headers A hashmap of http headers.
- * @param eventHandler The event handler for handling returned
- * data. Callbacks will be made on the supplied instance.
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- */
- public RequestHandle queueRequest(
- String url, String method,
- Map<String, String> headers, EventHandler eventHandler,
- InputStream bodyProvider, int bodyLength) {
- WebAddress uri = new WebAddress(url);
- return queueRequest(url, uri, method, headers, eventHandler,
- bodyProvider, bodyLength);
- }
-
- /**
- * Queues an HTTP request
- * @param url The url to load.
- * @param uri The uri of the url to load.
- * @param method "GET" or "POST."
- * @param headers A hashmap of http headers.
- * @param eventHandler The event handler for handling returned
- * data. Callbacks will be made on the supplied instance.
- * @param bodyProvider InputStream providing HTTP body, null if none
- * @param bodyLength length of body, must be 0 if bodyProvider is null
- */
- public RequestHandle queueRequest(
- String url, WebAddress uri, String method, Map<String, String> headers,
- EventHandler eventHandler,
- InputStream bodyProvider, int bodyLength) {
-
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.queueRequest " + uri);
-
- // Ensure there is an eventHandler set
- if (eventHandler == null) {
- eventHandler = new LoggingEventHandler();
- }
-
- /* Create and queue request */
- Request req;
- HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
-
- // set up request
- req = new Request(method, httpHost, mProxyHost, uri.getPath(), bodyProvider,
- bodyLength, eventHandler, headers);
-
- queueRequest(req, false);
-
- mActivePool.mTotalRequest++;
-
- // dump();
- mActivePool.startConnectionThread();
-
- return new RequestHandle(
- this, url, uri, method, headers, bodyProvider, bodyLength,
- req);
- }
-
- private static class SyncFeeder implements RequestFeeder {
- // This is used in the case where the request fails and needs to be
- // requeued into the RequestFeeder.
- private Request mRequest;
- SyncFeeder() {
- }
- public Request getRequest() {
- Request r = mRequest;
- mRequest = null;
- return r;
- }
- public Request getRequest(HttpHost host) {
- return getRequest();
- }
- public boolean haveRequest(HttpHost host) {
- return mRequest != null;
- }
- public void requeueRequest(Request r) {
- mRequest = r;
- }
- }
-
- public RequestHandle queueSynchronousRequest(String url, WebAddress uri,
- String method, Map<String, String> headers,
- EventHandler eventHandler, InputStream bodyProvider,
- int bodyLength) {
- if (HttpLog.LOGV) {
- HttpLog.v("RequestQueue.dispatchSynchronousRequest " + uri);
- }
-
- HttpHost host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
-
- Request req = new Request(method, host, mProxyHost, uri.getPath(),
- bodyProvider, bodyLength, eventHandler, headers);
-
- // Open a new connection that uses our special RequestFeeder
- // implementation.
- host = determineHost(host);
- Connection conn = Connection.getConnection(mContext, host, mProxyHost,
- new SyncFeeder());
-
- // TODO: I would like to process the request here but LoadListener
- // needs a RequestHandle to process some messages.
- return new RequestHandle(this, url, uri, method, headers, bodyProvider,
- bodyLength, req, conn);
-
- }
-
- // Chooses between the proxy and the request's host.
- private HttpHost determineHost(HttpHost host) {
- // There used to be a comment in ConnectionThread about t-mob's proxy
- // being really bad about https. But, HttpsConnection actually looks
- // for a proxy and connects through it anyway. I think that this check
- // is still valid because if a site is https, we will use
- // HttpsConnection rather than HttpConnection if the proxy address is
- // not secure.
- return (mProxyHost == null || "https".equals(host.getSchemeName()))
- ? host : mProxyHost;
- }
-
- /**
- * @return true iff there are any non-active requests pending
- */
- synchronized boolean requestsPending() {
- return !mPending.isEmpty();
- }
-
-
- /**
- * debug tool: prints request queue to log
- */
- synchronized void dump() {
- HttpLog.v("dump()");
- StringBuilder dump = new StringBuilder();
- int count = 0;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter;
-
- // mActivePool.log(dump);
-
- if (!mPending.isEmpty()) {
- iter = mPending.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
- String hostName = entry.getKey().getHostName();
- StringBuilder line = new StringBuilder("p" + count++ + " " + hostName + " ");
-
- LinkedList<Request> reqList = entry.getValue();
- ListIterator reqIter = reqList.listIterator(0);
- while (iter.hasNext()) {
- Request request = (Request)iter.next();
- line.append(request + " ");
- }
- dump.append(line);
- dump.append("\n");
- }
- }
- HttpLog.v(dump.toString());
- }
-
- /*
- * RequestFeeder implementation
- */
- public synchronized Request getRequest() {
- Request ret = null;
-
- if (!mPending.isEmpty()) {
- ret = removeFirst(mPending);
- }
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.getRequest() => " + ret);
- return ret;
- }
-
- /**
- * @return a request for given host if possible
- */
- public synchronized Request getRequest(HttpHost host) {
- Request ret = null;
-
- if (mPending.containsKey(host)) {
- LinkedList<Request> reqList = mPending.get(host);
- ret = reqList.removeFirst();
- if (reqList.isEmpty()) {
- mPending.remove(host);
- }
- }
- if (HttpLog.LOGV) HttpLog.v("RequestQueue.getRequest(" + host + ") => " + ret);
- return ret;
- }
-
- /**
- * @return true if a request for this host is available
- */
- public synchronized boolean haveRequest(HttpHost host) {
- return mPending.containsKey(host);
- }
-
- /**
- * Put request back on head of queue
- */
- public void requeueRequest(Request request) {
- queueRequest(request, true);
- }
-
- /**
- * This must be called to cleanly shutdown RequestQueue
- */
- public void shutdown() {
- mActivePool.shutdown();
- }
-
- protected synchronized void queueRequest(Request request, boolean head) {
- HttpHost host = request.mProxyHost == null ? request.mHost : request.mProxyHost;
- LinkedList<Request> reqList;
- if (mPending.containsKey(host)) {
- reqList = mPending.get(host);
- } else {
- reqList = new LinkedList<Request>();
- mPending.put(host, reqList);
- }
- if (head) {
- reqList.addFirst(request);
- } else {
- reqList.add(request);
- }
- }
-
-
- public void startTiming() {
- mActivePool.startTiming();
- }
-
- public void stopTiming() {
- mActivePool.stopTiming();
- }
-
- /* helper */
- private Request removeFirst(LinkedHashMap<HttpHost, LinkedList<Request>> requestQueue) {
- Request ret = null;
- Iterator<Map.Entry<HttpHost, LinkedList<Request>>> iter = requestQueue.entrySet().iterator();
- if (iter.hasNext()) {
- Map.Entry<HttpHost, LinkedList<Request>> entry = iter.next();
- LinkedList<Request> reqList = entry.getValue();
- ret = reqList.removeFirst();
- if (reqList.isEmpty()) {
- requestQueue.remove(entry.getKey());
- }
- }
- return ret;
- }
-
- /**
- * This interface is exposed to each connection
- */
- interface ConnectionManager {
- HttpHost getProxyHost();
- Connection getConnection(Context context, HttpHost host);
- boolean recycleConnection(Connection connection);
- }
-}
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 7785f2b..47e8e69 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -301,7 +301,7 @@
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
- throw new RuntimeException("An error occured while executing doInBackground()",
+ throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cd45cfb..4dadda2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -592,6 +592,86 @@
}
}
+ /**
+ * Optional detailed information that can go into a history step. This is typically
+ * generated each time the battery level changes.
+ */
+ public final static class HistoryStepDetails {
+ // Time (in 1/100 second) spent in user space and the kernel since the last step.
+ public int userTime;
+ public int systemTime;
+
+ // Top three apps using CPU in the last step, with times in 1/100 second.
+ public int appCpuUid1;
+ public int appCpuUTime1;
+ public int appCpuSTime1;
+ public int appCpuUid2;
+ public int appCpuUTime2;
+ public int appCpuSTime2;
+ public int appCpuUid3;
+ public int appCpuUTime3;
+ public int appCpuSTime3;
+
+ // Information from /proc/stat
+ public int statUserTime;
+ public int statSystemTime;
+ public int statIOWaitTime;
+ public int statIrqTime;
+ public int statSoftIrqTime;
+ public int statIdlTime;
+
+ public HistoryStepDetails() {
+ clear();
+ }
+
+ public void clear() {
+ userTime = systemTime = 0;
+ appCpuUid1 = appCpuUid2 = appCpuUid3 = -1;
+ appCpuUTime1 = appCpuSTime1 = appCpuUTime2 = appCpuSTime2
+ = appCpuUTime3 = appCpuSTime3 = 0;
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(userTime);
+ out.writeInt(systemTime);
+ out.writeInt(appCpuUid1);
+ out.writeInt(appCpuUTime1);
+ out.writeInt(appCpuSTime1);
+ out.writeInt(appCpuUid2);
+ out.writeInt(appCpuUTime2);
+ out.writeInt(appCpuSTime2);
+ out.writeInt(appCpuUid3);
+ out.writeInt(appCpuUTime3);
+ out.writeInt(appCpuSTime3);
+ out.writeInt(statUserTime);
+ out.writeInt(statSystemTime);
+ out.writeInt(statIOWaitTime);
+ out.writeInt(statIrqTime);
+ out.writeInt(statSoftIrqTime);
+ out.writeInt(statIdlTime);
+ }
+
+ public void readFromParcel(Parcel in) {
+ userTime = in.readInt();
+ systemTime = in.readInt();
+ appCpuUid1 = in.readInt();
+ appCpuUTime1 = in.readInt();
+ appCpuSTime1 = in.readInt();
+ appCpuUid2 = in.readInt();
+ appCpuUTime2 = in.readInt();
+ appCpuSTime2 = in.readInt();
+ appCpuUid3 = in.readInt();
+ appCpuUTime3 = in.readInt();
+ appCpuSTime3 = in.readInt();
+ statUserTime = in.readInt();
+ statSystemTime = in.readInt();
+ statIOWaitTime = in.readInt();
+ statIrqTime = in.readInt();
+ statSoftIrqTime = in.readInt();
+ statIdlTime = in.readInt();
+ }
+ }
+
public final static class HistoryItem implements Parcelable {
public HistoryItem next;
@@ -687,6 +767,9 @@
// Kernel wakeup reason at this point.
public HistoryTag wakeReasonTag;
+ // Non-null when there is more detailed information at this step.
+ public HistoryStepDetails stepDetails;
+
public static final int EVENT_FLAG_START = 0x8000;
public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -3692,10 +3775,115 @@
}
}
pw.println();
+ if (rec.stepDetails != null) {
+ if (!checkin) {
+ pw.print(" Details: cpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print("u+");
+ pw.print(rec.stepDetails.systemTime);
+ pw.print("s");
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ pw.print(" (");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ pw.print(", ");
+ printStepCpuUidDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ pw.print(')');
+ }
+ pw.println();
+ pw.print(" /proc/stat=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(" usr, ");
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(" sys, ");
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(" io, ");
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(" irq, ");
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(" sirq, ");
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.print(" idle");
+ int totalRun = rec.stepDetails.statUserTime + rec.stepDetails.statSystemTime
+ + rec.stepDetails.statIOWaitTime + rec.stepDetails.statIrqTime
+ + rec.stepDetails.statSoftIrqTime;
+ int total = totalRun + rec.stepDetails.statIdlTime;
+ if (total > 0) {
+ pw.print(" (");
+ float perc = ((float)totalRun) / ((float)total) * 100;
+ pw.print(String.format("%.1f%%", perc));
+ pw.print(" of ");
+ StringBuilder sb = new StringBuilder(64);
+ formatTimeMsNoSpace(sb, total*10);
+ pw.print(sb);
+ pw.print(")");
+ }
+ pw.println();
+ } else {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
+ pw.print(rec.stepDetails.userTime);
+ pw.print(":");
+ pw.print(rec.stepDetails.systemTime);
+ if (rec.stepDetails.appCpuUid1 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid1,
+ rec.stepDetails.appCpuUTime1, rec.stepDetails.appCpuSTime1);
+ if (rec.stepDetails.appCpuUid2 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid2,
+ rec.stepDetails.appCpuUTime2, rec.stepDetails.appCpuSTime2);
+ }
+ if (rec.stepDetails.appCpuUid3 >= 0) {
+ printStepCpuUidCheckinDetails(pw, rec.stepDetails.appCpuUid3,
+ rec.stepDetails.appCpuUTime3, rec.stepDetails.appCpuSTime3);
+ }
+ }
+ pw.println();
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(",0,Dpst=");
+ pw.print(rec.stepDetails.statUserTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSystemTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIOWaitTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statSoftIrqTime);
+ pw.print(',');
+ pw.print(rec.stepDetails.statIdlTime);
+ pw.println();
+ }
+ }
oldState = rec.states;
oldState2 = rec.states2;
}
}
+
+ private void printStepCpuUidDetails(PrintWriter pw, int uid, int utime, int stime) {
+ UserHandle.formatUid(pw, uid);
+ pw.print("=");
+ pw.print(utime);
+ pw.print("u+");
+ pw.print(stime);
+ pw.print("s");
+ }
+
+ private void printStepCpuUidCheckinDetails(PrintWriter pw, int uid, int utime, int stime) {
+ pw.print('/');
+ pw.print(uid);
+ pw.print(":");
+ pw.print(utime);
+ pw.print(":");
+ pw.print(stime);
+ }
}
private void printSizeValue(PrintWriter pw, long size) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index eb86e7e..36fc4f9 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -680,6 +680,7 @@
}
}
+ /* TODO: Figure out issue with checks failing
if (!TextUtils.isEmpty(bootimage)) {
if (!Objects.equals(system, bootimage)) {
Slog.e(TAG, "Mismatched fingerprints; system reported " + system
@@ -703,6 +704,7 @@
return false;
}
}
+ */
return true;
}
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b5295fb..236003b 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -21,6 +21,7 @@
import android.content.pm.UserInfo;
import android.content.RestrictionEntry;
import android.graphics.Bitmap;
+import android.os.ParcelFileDescriptor;
/**
* {@hide}
@@ -32,7 +33,7 @@
boolean removeUser(int userHandle);
void setUserName(int userHandle, String name);
void setUserIcon(int userHandle, in Bitmap icon);
- Bitmap getUserIcon(int userHandle);
+ ParcelFileDescriptor getUserIcon(int userHandle);
List<UserInfo> getUsers(boolean excludeDying);
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
UserInfo getProfileParent(int userHandle);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index d52dd30..e303f61 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -205,6 +205,20 @@
public static final int DOZE_WAKE_LOCK = 0x00000040;
/**
+ * Wake lock level: Keep the device awake enough to allow drawing to occur.
+ * <p>
+ * This is used by the window manager to allow applications to draw while the
+ * system is dozing. It currently has no effect unless the power manager is in
+ * the dozing state.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * {@hide}
+ */
+ public static final int DRAW_WAKE_LOCK = 0x00000080;
+
+ /**
* Mask for the wake lock level component of a combined wake lock level and flags integer.
*
* @hide
@@ -489,6 +503,7 @@
case FULL_WAKE_LOCK:
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
case DOZE_WAKE_LOCK:
+ case DRAW_WAKE_LOCK:
break;
default:
throw new IllegalArgumentException("Must specify a valid wake lock level.");
diff --git a/core/java/android/os/UEventObserver.java b/core/java/android/os/UEventObserver.java
index 9dbfd50..5c80ca6 100644
--- a/core/java/android/os/UEventObserver.java
+++ b/core/java/android/os/UEventObserver.java
@@ -22,13 +22,13 @@
import java.util.HashMap;
/**
- * UEventObserver is an abstract class that receives UEvent's from the kernel.<p>
+ * UEventObserver is an abstract class that receives UEvents from the kernel.<p>
*
* Subclass UEventObserver, implementing onUEvent(UEvent event), then call
* startObserving() with a match string. The UEvent thread will then call your
* onUEvent() method when a UEvent occurs that contains your match string.<p>
*
- * Call stopObserving() to stop receiving UEvent's.<p>
+ * Call stopObserving() to stop receiving UEvents.<p>
*
* There is only one UEvent thread per process, even if that process has
* multiple UEventObserver subclass instances. The UEvent thread starts when
@@ -78,7 +78,7 @@
}
/**
- * Begin observation of UEvent's.<p>
+ * Begin observation of UEvents.<p>
* This method will cause the UEvent thread to start if this is the first
* invocation of startObserving in this process.<p>
* Once called, the UEvent thread will call onUEvent() when an incoming
@@ -103,7 +103,7 @@
}
/**
- * End observation of UEvent's.<p>
+ * End observation of UEvents.<p>
* This process's UEvent thread will never call onUEvent() on this
* UEventObserver after this call. Repeated calls have no effect.
*/
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d124a49..650f3b3 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -22,6 +22,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
@@ -30,6 +31,7 @@
import com.android.internal.R;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -114,6 +116,7 @@
/**
* Specifies if a user is disallowed from configuring bluetooth.
+ * This does <em>not</em> restrict the user from turning bluetooth on or off.
* The default value is <code>false</code>.
* <p/>This restriction has no effect in a managed profile.
*
@@ -1083,11 +1086,21 @@
*/
public Bitmap getUserIcon(int userHandle) {
try {
- return mService.getUserIcon(userHandle);
+ ParcelFileDescriptor fd = mService.getUserIcon(userHandle);
+ if (fd != null) {
+ try {
+ return BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
+ } finally {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ }
+ }
} catch (RemoteException re) {
Log.w(TAG, "Could not get the user icon ", re);
- return null;
}
+ return null;
}
/**
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index b65eac7..1b226c1 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -17,6 +17,8 @@
package android.preference;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -168,7 +170,7 @@
*
* @param dialogIconRes The icon, as a resource ID.
*/
- public void setDialogIcon(int dialogIconRes) {
+ public void setDialogIcon(@DrawableRes int dialogIconRes) {
mDialogIcon = getContext().getDrawable(dialogIconRes);
}
@@ -194,7 +196,7 @@
* @see #setPositiveButtonText(CharSequence)
* @param positiveButtonTextResId The positive button text as a resource.
*/
- public void setPositiveButtonText(int positiveButtonTextResId) {
+ public void setPositiveButtonText(@StringRes int positiveButtonTextResId) {
setPositiveButtonText(getContext().getString(positiveButtonTextResId));
}
@@ -222,7 +224,7 @@
* @see #setNegativeButtonText(CharSequence)
* @param negativeButtonTextResId The negative button text as a resource.
*/
- public void setNegativeButtonText(int negativeButtonTextResId) {
+ public void setNegativeButtonText(@StringRes int negativeButtonTextResId) {
setNegativeButtonText(getContext().getString(negativeButtonTextResId));
}
diff --git a/core/java/android/preference/GenericInflater.java b/core/java/android/preference/GenericInflater.java
index 7de7d1c..c84dbf1 100644
--- a/core/java/android/preference/GenericInflater.java
+++ b/core/java/android/preference/GenericInflater.java
@@ -23,6 +23,8 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnyRes;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
@@ -216,7 +218,7 @@
* this is the root item; otherwise it is the root of the inflated
* XML file.
*/
- public T inflate(int resource, P root) {
+ public T inflate(@XmlRes int resource, P root) {
return inflate(resource, root, root != null);
}
@@ -256,7 +258,7 @@
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
- public T inflate(int resource, P root, boolean attachToRoot) {
+ public T inflate(@XmlRes int resource, P root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getXml(resource);
try {
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index 9482a72..2700373 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -91,7 +92,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -119,7 +120,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/MultiCheckPreference.java b/core/java/android/preference/MultiCheckPreference.java
index 57c906d..c1260a4 100644
--- a/core/java/android/preference/MultiCheckPreference.java
+++ b/core/java/android/preference/MultiCheckPreference.java
@@ -18,6 +18,7 @@
import java.util.Arrays;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -96,7 +97,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -126,7 +127,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValuesCS(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/MultiSelectListPreference.java b/core/java/android/preference/MultiSelectListPreference.java
index 6c4c20f..138bd878 100644
--- a/core/java/android/preference/MultiSelectListPreference.java
+++ b/core/java/android/preference/MultiSelectListPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.ArrayRes;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
@@ -87,7 +88,7 @@
* @see #setEntries(CharSequence[])
* @param entriesResId The entries array as a resource.
*/
- public void setEntries(int entriesResId) {
+ public void setEntries(@ArrayRes int entriesResId) {
setEntries(getContext().getResources().getTextArray(entriesResId));
}
@@ -115,7 +116,7 @@
* @see #setEntryValues(CharSequence[])
* @param entryValuesResId The entry values array as a resource.
*/
- public void setEntryValues(int entryValuesResId) {
+ public void setEntryValues(@ArrayRes int entryValuesResId) {
setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
}
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 0224c73..78928b2 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -18,6 +18,9 @@
import com.android.internal.util.CharSequences;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -424,7 +427,7 @@
* a {@link View}.
* @see #setWidgetLayoutResource(int)
*/
- public void setLayoutResource(int layoutResId) {
+ public void setLayoutResource(@LayoutRes int layoutResId) {
if (layoutResId != mLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
@@ -438,6 +441,7 @@
*
* @return The layout resource ID.
*/
+ @LayoutRes
public int getLayoutResource() {
return mLayoutResId;
}
@@ -452,7 +456,7 @@
* main layout.
* @see #setLayoutResource(int)
*/
- public void setWidgetLayoutResource(int widgetLayoutResId) {
+ public void setWidgetLayoutResource(@LayoutRes int widgetLayoutResId) {
if (widgetLayoutResId != mWidgetLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
@@ -465,6 +469,7 @@
*
* @return The layout resource ID.
*/
+ @LayoutRes
public int getWidgetLayoutResource() {
return mWidgetLayoutResId;
}
@@ -648,7 +653,7 @@
* @see #setTitle(CharSequence)
* @param titleResId The title as a resource ID.
*/
- public void setTitle(int titleResId) {
+ public void setTitle(@StringRes int titleResId) {
setTitle(mContext.getString(titleResId));
mTitleRes = titleResId;
}
@@ -660,6 +665,7 @@
* @return The title resource.
* @see #setTitle(int)
*/
+ @StringRes
public int getTitleRes() {
return mTitleRes;
}
@@ -696,7 +702,7 @@
* @see #setIcon(Drawable)
* @param iconResId The icon as a resource ID.
*/
- public void setIcon(int iconResId) {
+ public void setIcon(@DrawableRes int iconResId) {
mIconResId = iconResId;
setIcon(mContext.getDrawable(iconResId));
}
@@ -739,7 +745,7 @@
* @see #setSummary(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummary(int summaryResId) {
+ public void setSummary(@StringRes int summaryResId) {
setSummary(mContext.getString(summaryResId));
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 04cd7d5..06666f4 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,6 +16,9 @@
package android.preference;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.XmlRes;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.FragmentManager;
@@ -337,6 +340,7 @@
* Resource ID of title of the header that is shown to the user.
* @attr ref android.R.styleable#PreferenceHeader_title
*/
+ @StringRes
public int titleRes;
/**
@@ -349,6 +353,7 @@
* Resource ID of optional summary describing what this header controls.
* @attr ref android.R.styleable#PreferenceHeader_summary
*/
+ @StringRes
public int summaryRes;
/**
@@ -361,6 +366,7 @@
* Resource ID of optional text to show as the title in the bread crumb.
* @attr ref android.R.styleable#PreferenceHeader_breadCrumbTitle
*/
+ @StringRes
public int breadCrumbTitleRes;
/**
@@ -373,6 +379,7 @@
* Resource ID of optional text to show as the short title in the bread crumb.
* @attr ref android.R.styleable#PreferenceHeader_breadCrumbShortTitle
*/
+ @StringRes
public int breadCrumbShortTitleRes;
/**
@@ -525,7 +532,7 @@
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Theming for the PreferenceActivity layout and for the Preference Header(s) layout
@@ -797,7 +804,7 @@
* @param resid The XML resource to load and parse.
* @param target The list in which the parsed headers should be placed.
*/
- public void loadHeadersFromResource(int resid, List<Header> target) {
+ public void loadHeadersFromResource(@XmlRes int resid, List<Header> target) {
XmlResourceParser parser = null;
try {
parser = getResources().getXml(resid);
@@ -1086,7 +1093,7 @@
* fragment.
*/
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
- int titleRes, int shortTitleRes) {
+ @StringRes int titleRes, int shortTitleRes) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
@@ -1124,7 +1131,8 @@
* this set of preferences.
*/
public void startWithFragment(String fragmentName, Bundle args,
- Fragment resultTo, int resultRequestCode, int titleRes, int shortTitleRes) {
+ Fragment resultTo, int resultRequestCode, @StringRes int titleRes,
+ @StringRes int shortTitleRes) {
Intent intent = onBuildStartFragmentIntent(fragmentName, args, titleRes, shortTitleRes);
if (resultTo == null) {
startActivity(intent);
@@ -1343,9 +1351,9 @@
* preference panel is done. The launched panel must use
* {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
* @param resultRequestCode If resultTo is non-null, this is the caller's
- * request code to be received with the resut.
+ * request code to be received with the result.
*/
- public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
+ public void startPreferencePanel(String fragmentClass, Bundle args, @StringRes int titleRes,
CharSequence titleText, Fragment resultTo, int resultRequestCode) {
if (mSinglePane) {
startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0);
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index e95e6e2..29f9ca1 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
@@ -153,15 +154,15 @@
}
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE);
mPreferenceManager.setFragment(this);
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
TypedArray a = getActivity().obtainStyledAttributes(null,
com.android.internal.R.styleable.PreferenceFragment,
@@ -177,7 +178,7 @@
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mHavePrefs) {
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index 0a0e625..55ee77a 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.XmlRes;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
@@ -263,7 +264,7 @@
* root).
* @hide
*/
- public PreferenceScreen inflateFromResource(Context context, int resId,
+ public PreferenceScreen inflateFromResource(Context context, @XmlRes int resId,
PreferenceScreen rootPreferences) {
// Block commits
setNoCommit(true);
@@ -438,7 +439,7 @@
* and clear it followed by a call to this method with this
* parameter set to true.
*/
- public static void setDefaultValues(Context context, int resId, boolean readAgain) {
+ public static void setDefaultValues(Context context, @XmlRes int resId, boolean readAgain) {
// Use the default shared preferences name and mode
setDefaultValues(context, getDefaultSharedPreferencesName(context),
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index c3dd4ce..30da0e7 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -174,6 +175,11 @@
}
if (mRingtone != null) {
try {
+ mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
+ .getAudioAttributes())
+ .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
+ AudioAttributes.FLAG_BYPASS_MUTE)
+ .build());
mRingtone.play();
} catch (Throwable e) {
Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
diff --git a/core/java/android/preference/SwitchPreference.java b/core/java/android/preference/SwitchPreference.java
index 53b5aad..9c3cefc 100644
--- a/core/java/android/preference/SwitchPreference.java
+++ b/core/java/android/preference/SwitchPreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -169,7 +170,7 @@
*
* @param resId The text as a string resource ID
*/
- public void setSwitchTextOn(int resId) {
+ public void setSwitchTextOn(@StringRes int resId) {
setSwitchTextOn(getContext().getString(resId));
}
@@ -179,7 +180,7 @@
*
* @param resId The text as a string resource ID
*/
- public void setSwitchTextOff(int resId) {
+ public void setSwitchTextOff(@StringRes int resId) {
setSwitchTextOff(getContext().getString(resId));
}
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 3823b27..7037aca 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
@@ -116,7 +117,7 @@
* @see #setSummaryOn(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummaryOn(int summaryResId) {
+ public void setSummaryOn(@StringRes int summaryResId) {
setSummaryOn(getContext().getString(summaryResId));
}
@@ -144,7 +145,7 @@
* @see #setSummaryOff(CharSequence)
* @param summaryResId The summary as a resource.
*/
- public void setSummaryOff(int summaryResId) {
+ public void setSummaryOff(@StringRes int summaryResId) {
setSummaryOff(getContext().getString(summaryResId));
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f023df7..266922d 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -33,7 +33,9 @@
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DataUsageFeedback;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
@@ -336,22 +338,33 @@
// that was encoded into call log databases.
/**
- * The component name of the account in string form.
+ * The component name of the account used to place or receive the call; in string form.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
/**
- * The identifier of a account that is unique to a specified component.
+ * The identifier for the account used to place or receive the call.
* <P>Type: TEXT</P>
*/
public static final String PHONE_ACCOUNT_ID = "subscription_id";
/**
- * The identifier of a account that is unique to a specified component. Equivalent value
- * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
+ * The address associated with the account used to place or receive the call; in string
+ * form. For SIM-based calls, this is the user's own phone number.
+ * <P>Type: TEXT</P>
+ *
+ * @hide
+ */
+ public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
+
+ /**
+ * The subscription ID used to place this call. This is no longer used and has been
+ * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
+ * For ContactsProvider internal use only.
* <P>Type: INTEGER</P>
*
+ * @Deprecated
* @hide
*/
public static final String SUB_ID = "sub_id";
@@ -422,6 +435,19 @@
final ContentResolver resolver = context.getContentResolver();
int numberPresentation = PRESENTATION_ALLOWED;
+ TelecomManager tm = null;
+ try {
+ tm = TelecomManager.from(context);
+ } catch (UnsupportedOperationException e) {}
+
+ String accountAddress = null;
+ if (tm != null && accountHandle != null) {
+ PhoneAccount account = tm.getPhoneAccount(accountHandle);
+ if (account != null) {
+ accountAddress = account.getSubscriptionAddress().getSchemeSpecificPart();
+ }
+ }
+
// Remap network specified number presentation types
// PhoneConstants.PRESENTATION_xxx to calllog number presentation types
// Calls.PRESENTATION_xxx, in order to insulate the persistent calllog
@@ -463,6 +489,7 @@
}
values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
values.put(PHONE_ACCOUNT_ID, accountId);
+ values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
values.put(NEW, Integer.valueOf(1));
if (callType == MISSED_TYPE) {
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 736ec54..5afbd6d 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -638,7 +638,6 @@
static Bitmap getThumbnail(ContentResolver cr, long origId, long groupId, int kind,
BitmapFactory.Options options, Uri baseUri, boolean isVideo) {
Bitmap bitmap = null;
- String filePath = null;
// Log.v(TAG, "getThumbnail: origId="+origId+", kind="+kind+", isVideo="+isVideo);
// If the magic is non-zero, we simply return thumbnail if it does exist.
// querying MediaProvider and simply return thumbnail.
@@ -710,18 +709,18 @@
Uri uri = Uri.parse(
baseUri.buildUpon().appendPath(String.valueOf(origId))
.toString().replaceFirst("thumbnails", "media"));
- if (filePath == null) {
- if (c != null) c.close();
- c = cr.query(uri, PROJECTION, null, null, null);
- if (c == null || !c.moveToFirst()) {
- return null;
- }
- filePath = c.getString(1);
+ if (c != null) c.close();
+ c = cr.query(uri, PROJECTION, null, null, null);
+ if (c == null || !c.moveToFirst()) {
+ return null;
}
- if (isVideo) {
- bitmap = ThumbnailUtils.createVideoThumbnail(filePath, kind);
- } else {
- bitmap = ThumbnailUtils.createImageThumbnail(filePath, kind);
+ String filePath = c.getString(1);
+ if (filePath != null) {
+ if (isVideo) {
+ bitmap = ThumbnailUtils.createVideoThumbnail(filePath, kind);
+ } else {
+ bitmap = ThumbnailUtils.createImageThumbnail(filePath, kind);
+ }
}
}
} catch (SQLiteException ex) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 250e80f..f084263 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -51,14 +51,21 @@
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.AndroidException;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ILockSettings;
import java.net.URISyntaxException;
+import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
/**
* The Settings provider contains global system-level device preferences.
@@ -1192,6 +1199,11 @@
public static final class System extends NameValueTable {
public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
+ /** @hide */
+ public static interface Validator {
+ public boolean validate(String value);
+ }
+
/**
* The content:// style URL for this table
*/
@@ -1294,13 +1306,53 @@
MOVED_TO_GLOBAL.add(Settings.Global.CERT_PIN_UPDATE_METADATA_URL);
}
+ private static final Validator sBooleanValidator =
+ new DiscreteValueValidator(new String[] {"0", "1"});
+
+ private static final Validator sNonNegativeIntegerValidator = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ return Integer.parseInt(value) >= 0;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ };
+
+ private static final Validator sUriValidator = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ Uri.decode(value);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+ };
+
+ private static final Validator sLenientIpAddressValidator = new Validator() {
+ private static final int MAX_IPV6_LENGTH = 45;
+
+ @Override
+ public boolean validate(String value) {
+ return value.length() <= MAX_IPV6_LENGTH;
+ }
+ };
+
/** @hide */
- public static void getMovedKeys(HashSet<String> outKeySet) {
+ public static void getMovedToGlobalSettings(Set<String> outKeySet) {
outKeySet.addAll(MOVED_TO_GLOBAL);
outKeySet.addAll(MOVED_TO_SECURE_THEN_GLOBAL);
}
/** @hide */
+ public static void getMovedToSecureSettings(Set<String> outKeySet) {
+ outKeySet.addAll(MOVED_TO_SECURE);
+ }
+
+ /** @hide */
public static void getNonLegacyMovedKeys(HashSet<String> outKeySet) {
outKeySet.addAll(MOVED_TO_GLOBAL);
}
@@ -1723,6 +1775,59 @@
putIntForUser(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0, userHandle);
}
+ private static final class DiscreteValueValidator implements Validator {
+ private final String[] mValues;
+
+ public DiscreteValueValidator(String[] values) {
+ mValues = values;
+ }
+
+ @Override
+ public boolean validate(String value) {
+ return ArrayUtils.contains(mValues, value);
+ }
+ }
+
+ private static final class InclusiveIntegerRangeValidator implements Validator {
+ private final int mMin;
+ private final int mMax;
+
+ public InclusiveIntegerRangeValidator(int min, int max) {
+ mMin = min;
+ mMax = max;
+ }
+
+ @Override
+ public boolean validate(String value) {
+ try {
+ final int intValue = Integer.parseInt(value);
+ return intValue >= mMin && intValue <= mMax;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ }
+
+ private static final class InclusiveFloatRangeValidator implements Validator {
+ private final float mMin;
+ private final float mMax;
+
+ public InclusiveFloatRangeValidator(float min, float max) {
+ mMin = min;
+ mMax = max;
+ }
+
+ @Override
+ public boolean validate(String value) {
+ try {
+ final float floatValue = Float.parseFloat(value);
+ return floatValue >= mMin && floatValue <= mMax;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ }
+
/**
* @deprecated Use {@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} instead
*/
@@ -1741,6 +1846,9 @@
*/
public static final String END_BUTTON_BEHAVIOR = "end_button_behavior";
+ private static final Validator END_BUTTON_BEHAVIOR_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 3);
+
/**
* END_BUTTON_BEHAVIOR value for "go home".
* @hide
@@ -1765,6 +1873,8 @@
*/
public static final String ADVANCED_SETTINGS = "advanced_settings";
+ private static final Validator ADVANCED_SETTINGS_VALIDATOR = sBooleanValidator;
+
/**
* ADVANCED_SETTINGS default value.
* @hide
@@ -1864,6 +1974,8 @@
@Deprecated
public static final String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
+ private static final Validator WIFI_USE_STATIC_IP_VALIDATOR = sBooleanValidator;
+
/**
* The static IP address.
* <p>
@@ -1874,6 +1986,8 @@
@Deprecated
public static final String WIFI_STATIC_IP = "wifi_static_ip";
+ private static final Validator WIFI_STATIC_IP_VALIDATOR = sLenientIpAddressValidator;
+
/**
* If using static IP, the gateway's IP address.
* <p>
@@ -1884,6 +1998,8 @@
@Deprecated
public static final String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
+ private static final Validator WIFI_STATIC_GATEWAY_VALIDATOR = sLenientIpAddressValidator;
+
/**
* If using static IP, the net mask.
* <p>
@@ -1894,6 +2010,8 @@
@Deprecated
public static final String WIFI_STATIC_NETMASK = "wifi_static_netmask";
+ private static final Validator WIFI_STATIC_NETMASK_VALIDATOR = sLenientIpAddressValidator;
+
/**
* If using static IP, the primary DNS's IP address.
* <p>
@@ -1904,6 +2022,8 @@
@Deprecated
public static final String WIFI_STATIC_DNS1 = "wifi_static_dns1";
+ private static final Validator WIFI_STATIC_DNS1_VALIDATOR = sLenientIpAddressValidator;
+
/**
* If using static IP, the secondary DNS's IP address.
* <p>
@@ -1914,6 +2034,7 @@
@Deprecated
public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2";
+ private static final Validator WIFI_STATIC_DNS2_VALIDATOR = sLenientIpAddressValidator;
/**
* Determines whether remote devices may discover and/or connect to
@@ -1926,6 +2047,9 @@
public static final String BLUETOOTH_DISCOVERABILITY =
"bluetooth_discoverability";
+ private static final Validator BLUETOOTH_DISCOVERABILITY_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 2);
+
/**
* Bluetooth discoverability timeout. If this value is nonzero, then
* Bluetooth becomes discoverable for a certain number of seconds,
@@ -1934,6 +2058,9 @@
public static final String BLUETOOTH_DISCOVERABILITY_TIMEOUT =
"bluetooth_discoverability_timeout";
+ private static final Validator BLUETOOTH_DISCOVERABILITY_TIMEOUT_VALIDATOR =
+ sNonNegativeIntegerValidator;
+
/**
* @deprecated Use {@link android.provider.Settings.Secure#LOCK_PATTERN_ENABLED}
* instead
@@ -1957,7 +2084,6 @@
public static final String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED =
"lock_pattern_tactile_feedback_enabled";
-
/**
* A formatted string of the next alarm that is set, or the empty string
* if there is no alarm set.
@@ -1967,11 +2093,32 @@
@Deprecated
public static final String NEXT_ALARM_FORMATTED = "next_alarm_formatted";
+ private static final Validator NEXT_ALARM_FORMATTED_VALIDATOR = new Validator() {
+ private static final int MAX_LENGTH = 1000;
+
+ @Override
+ public boolean validate(String value) {
+ // TODO: No idea what the correct format is.
+ return value == null || value.length() < MAX_LENGTH;
+ }
+ };
+
/**
* Scaling factor for fonts, float.
*/
public static final String FONT_SCALE = "font_scale";
+ private static final Validator FONT_SCALE_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ return Float.parseFloat(value) >= 0;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ };
+
/**
* Name of an application package to be debugged.
*
@@ -1996,6 +2143,8 @@
@Deprecated
public static final String DIM_SCREEN = "dim_screen";
+ private static final Validator DIM_SCREEN_VALIDATOR = sBooleanValidator;
+
/**
* The amount of time in milliseconds before the device goes to sleep or begins
* to dream after a period of inactivity. This value is also known as the
@@ -2004,16 +2153,23 @@
*/
public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
+ private static final Validator SCREEN_OFF_TIMEOUT_VALIDATOR = sNonNegativeIntegerValidator;
+
/**
* The screen backlight brightness between 0 and 255.
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
+ private static final Validator SCREEN_BRIGHTNESS_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 255);
+
/**
* Control whether to enable automatic brightness mode.
*/
public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
+ private static final Validator SCREEN_BRIGHTNESS_MODE_VALIDATOR = sBooleanValidator;
+
/**
* Adjustment to auto-brightness to make it generally more (>0.0 <1.0)
* or less (<0.0 >-1.0) bright.
@@ -2021,6 +2177,9 @@
*/
public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj";
+ private static final Validator SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR =
+ new InclusiveFloatRangeValidator(-1, 1);
+
/**
* SCREEN_BRIGHTNESS_MODE value for manual mode.
*/
@@ -2056,12 +2215,18 @@
*/
public static final String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
- /**
+ private static final Validator MODE_RINGER_STREAMS_AFFECTED_VALIDATOR =
+ sNonNegativeIntegerValidator;
+
+ /**
* Determines which streams are affected by mute. The
* stream type's bit should be set to 1 if it should be muted when a mute request
* is received.
*/
- public static final String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
+ public static final String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
+
+ private static final Validator MUTE_STREAMS_AFFECTED_VALIDATOR =
+ sNonNegativeIntegerValidator;
/**
* Whether vibrate is on for different events. This is used internally,
@@ -2069,6 +2234,8 @@
*/
public static final String VIBRATE_ON = "vibrate_on";
+ private static final Validator VIBRATE_ON_VALIDATOR = sBooleanValidator;
+
/**
* If 1, redirects the system vibrator to all currently attached input devices
* that support vibration. If there are no such input devices, then the system
@@ -2083,6 +2250,8 @@
*/
public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";
+ private static final Validator VIBRATE_INPUT_DEVICES_VALIDATOR = sBooleanValidator;
+
/**
* Ringer volume. This is used internally, changing this value will not
* change the volume. See AudioManager.
@@ -2131,6 +2300,9 @@
*/
public static final String VOLUME_MASTER = "volume_master";
+ private static final Validator VOLUME_MASTER_VALIDATOR =
+ new InclusiveFloatRangeValidator(0, 1);
+
/**
* Master volume mute (int 1 = mute, 0 = not muted).
*
@@ -2138,6 +2310,8 @@
*/
public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
+ private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator;
+
/**
* Microphone mute (int 1 = mute, 0 = not muted).
*
@@ -2145,6 +2319,8 @@
*/
public static final String MICROPHONE_MUTE = "microphone_mute";
+ private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
+
/**
* Whether the notifications should use the ring volume (value of 1) or
* a separate notification volume (value of 0). In most cases, users
@@ -2163,6 +2339,8 @@
public static final String NOTIFICATIONS_USE_RING_VOLUME =
"notifications_use_ring_volume";
+ private static final Validator NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR = sBooleanValidator;
+
/**
* Whether silent mode should allow vibration feedback. This is used
* internally in AudioService and the Sound settings activity to
@@ -2177,6 +2355,8 @@
*/
public static final String VIBRATE_IN_SILENT = "vibrate_in_silent";
+ private static final Validator VIBRATE_IN_SILENT_VALIDATOR = sBooleanValidator;
+
/**
* The mapping of stream type (integer) to its setting.
*/
@@ -2203,6 +2383,8 @@
*/
public static final String RINGTONE = "ringtone";
+ private static final Validator RINGTONE_VALIDATOR = sUriValidator;
+
/**
* A {@link Uri} that will point to the current default ringtone at any
* given time.
@@ -2221,6 +2403,8 @@
*/
public static final String NOTIFICATION_SOUND = "notification_sound";
+ private static final Validator NOTIFICATION_SOUND_VALIDATOR = sUriValidator;
+
/**
* A {@link Uri} that will point to the current default notification
* sound at any given time.
@@ -2237,6 +2421,8 @@
*/
public static final String ALARM_ALERT = "alarm_alert";
+ private static final Validator ALARM_ALERT_VALIDATOR = sUriValidator;
+
/**
* A {@link Uri} that will point to the current default alarm alert at
* any given time.
@@ -2252,30 +2438,52 @@
*/
public static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
+ private static final Validator MEDIA_BUTTON_RECEIVER_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ ComponentName.unflattenFromString(value);
+ return true;
+ } catch (NullPointerException e) {
+ return false;
+ }
+ }
+ };
+
/**
* Setting to enable Auto Replace (AutoText) in text editors. 1 = On, 0 = Off
*/
public static final String TEXT_AUTO_REPLACE = "auto_replace";
+ private static final Validator TEXT_AUTO_REPLACE_VALIDATOR = sBooleanValidator;
+
/**
* Setting to enable Auto Caps in text editors. 1 = On, 0 = Off
*/
public static final String TEXT_AUTO_CAPS = "auto_caps";
+ private static final Validator TEXT_AUTO_CAPS_VALIDATOR = sBooleanValidator;
+
/**
* Setting to enable Auto Punctuate in text editors. 1 = On, 0 = Off. This
* feature converts two spaces to a "." and space.
*/
public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
+ private static final Validator TEXT_AUTO_PUNCTUATE_VALIDATOR = sBooleanValidator;
+
/**
* Setting to showing password characters in text editors. 1 = On, 0 = Off
*/
public static final String TEXT_SHOW_PASSWORD = "show_password";
+ private static final Validator TEXT_SHOW_PASSWORD_VALIDATOR = sBooleanValidator;
+
public static final String SHOW_GTALK_SERVICE_STATUS =
"SHOW_GTALK_SERVICE_STATUS";
+ private static final Validator SHOW_GTALK_SERVICE_STATUS_VALIDATOR = sBooleanValidator;
+
/**
* Name of activity to use for wallpaper on the home screen.
*
@@ -2284,6 +2492,18 @@
@Deprecated
public static final String WALLPAPER_ACTIVITY = "wallpaper_activity";
+ private static final Validator WALLPAPER_ACTIVITY_VALIDATOR = new Validator() {
+ private static final int MAX_LENGTH = 1000;
+
+ @Override
+ public boolean validate(String value) {
+ if (value != null && value.length() > MAX_LENGTH) {
+ return false;
+ }
+ return ComponentName.unflattenFromString(value) != null;
+ }
+ };
+
/**
* @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME}
* instead
@@ -2305,6 +2525,10 @@
*/
public static final String TIME_12_24 = "time_12_24";
+ /** @hide */
+ public static final Validator TIME_12_24_VALIDATOR =
+ new DiscreteValueValidator(new String[] {"12", "24"});
+
/**
* Date format string
* mm/dd/yyyy
@@ -2313,6 +2537,19 @@
*/
public static final String DATE_FORMAT = "date_format";
+ /** @hide */
+ public static final Validator DATE_FORMAT_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ new SimpleDateFormat(value);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+ };
+
/**
* Whether the setup wizard has been run before (on first boot), or if
* it still needs to be run.
@@ -2322,6 +2559,9 @@
*/
public static final String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run";
+ /** @hide */
+ public static final Validator SETUP_WIZARD_HAS_RUN_VALIDATOR = sBooleanValidator;
+
/**
* Scaling factor for normal window animations. Setting to 0 will disable window
* animations.
@@ -2358,6 +2598,9 @@
*/
public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
+ /** @hide */
+ public static final Validator ACCELEROMETER_ROTATION_VALIDATOR = sBooleanValidator;
+
/**
* Default screen rotation when no other policy applies.
* When {@link #ACCELEROMETER_ROTATION} is zero and no on-screen Activity expresses a
@@ -2368,6 +2611,10 @@
*/
public static final String USER_ROTATION = "user_rotation";
+ /** @hide */
+ public static final Validator USER_ROTATION_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 3);
+
/**
* Control whether the rotation lock toggle in the System UI should be hidden.
* Typically this is done for accessibility purposes to make it harder for
@@ -2382,6 +2629,10 @@
public static final String HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY =
"hide_rotation_lock_toggle_for_accessibility";
+ /** @hide */
+ public static final Validator HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY_VALIDATOR =
+ sBooleanValidator;
+
/**
* Whether the phone vibrates when it is ringing due to an incoming call. This will
* be used by Phone and Setting apps; it shouldn't affect other apps.
@@ -2396,12 +2647,18 @@
*/
public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
+ /** @hide */
+ public static final Validator VIBRATE_WHEN_RINGING_VALIDATOR = sBooleanValidator;
+
/**
* Whether the audible DTMF tones are played by the dialer when dialing. The value is
* boolean (1 or 0).
*/
public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
+ /** @hide */
+ public static final Validator DTMF_TONE_WHEN_DIALING_VALIDATOR = sBooleanValidator;
+
/**
* CDMA only settings
* DTMF tone type played by the dialer when dialing.
@@ -2411,6 +2668,9 @@
*/
public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type";
+ /** @hide */
+ public static final Validator DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR = sBooleanValidator;
+
/**
* Whether the hearing aid is enabled. The value is
* boolean (1 or 0).
@@ -2418,6 +2678,9 @@
*/
public static final String HEARING_AID = "hearing_aid";
+ /** @hide */
+ public static final Validator HEARING_AID_VALIDATOR = sBooleanValidator;
+
/**
* CDMA only settings
* TTY Mode
@@ -2429,18 +2692,27 @@
*/
public static final String TTY_MODE = "tty_mode";
+ /** @hide */
+ public static final Validator TTY_MODE_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3);
+
/**
* Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
* boolean (1 or 0).
*/
public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
+ /** @hide */
+ public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = sBooleanValidator;
+
/**
* Whether the haptic feedback (long presses, ...) are enabled. The value is
* boolean (1 or 0).
*/
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+ /** @hide */
+ public static final Validator HAPTIC_FEEDBACK_ENABLED_VALIDATOR = sBooleanValidator;
+
/**
* @deprecated Each application that shows web suggestions should have its own
* setting for this.
@@ -2448,6 +2720,9 @@
@Deprecated
public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
+ /** @hide */
+ public static final Validator SHOW_WEB_SUGGESTIONS_VALIDATOR = sBooleanValidator;
+
/**
* Whether the notification LED should repeatedly flash when a notification is
* pending. The value is boolean (1 or 0).
@@ -2455,6 +2730,9 @@
*/
public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
+ /** @hide */
+ public static final Validator NOTIFICATION_LIGHT_PULSE_VALIDATOR = sBooleanValidator;
+
/**
* Show pointer location on screen?
* 0 = no
@@ -2463,6 +2741,9 @@
*/
public static final String POINTER_LOCATION = "pointer_location";
+ /** @hide */
+ public static final Validator POINTER_LOCATION_VALIDATOR = sBooleanValidator;
+
/**
* Show touch positions on screen?
* 0 = no
@@ -2471,6 +2752,9 @@
*/
public static final String SHOW_TOUCHES = "show_touches";
+ /** @hide */
+ public static final Validator SHOW_TOUCHES_VALIDATOR = sBooleanValidator;
+
/**
* Log raw orientation data from
* {@link com.android.server.policy.WindowOrientationListener} for use with the
@@ -2482,6 +2766,9 @@
public static final String WINDOW_ORIENTATION_LISTENER_LOG =
"window_orientation_listener_log";
+ /** @hide */
+ public static final Validator WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR = sBooleanValidator;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#POWER_SOUNDS_ENABLED}
* instead
@@ -2504,12 +2791,18 @@
*/
public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
+ /** @hide */
+ public static final Validator LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR = sBooleanValidator;
+
/**
* Whether the lockscreen should be completely disabled.
* @hide
*/
public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled";
+ /** @hide */
+ public static final Validator LOCKSCREEN_DISABLED_VALIDATOR = sBooleanValidator;
+
/**
* @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND}
* instead
@@ -2574,6 +2867,9 @@
*/
public static final String SIP_RECEIVE_CALLS = "sip_receive_calls";
+ /** @hide */
+ public static final Validator SIP_RECEIVE_CALLS_VALIDATOR = sBooleanValidator;
+
/**
* Call Preference String.
* "SIP_ALWAYS" : Always use SIP with network access
@@ -2582,18 +2878,28 @@
*/
public static final String SIP_CALL_OPTIONS = "sip_call_options";
+ /** @hide */
+ public static final Validator SIP_CALL_OPTIONS_VALIDATOR = new DiscreteValueValidator(
+ new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"});
+
/**
* One of the sip call options: Always use SIP with network access.
* @hide
*/
public static final String SIP_ALWAYS = "SIP_ALWAYS";
+ /** @hide */
+ public static final Validator SIP_ALWAYS_VALIDATOR = sBooleanValidator;
+
/**
* One of the sip call options: Only if destination is a SIP address.
* @hide
*/
public static final String SIP_ADDRESS_ONLY = "SIP_ADDRESS_ONLY";
+ /** @hide */
+ public static final Validator SIP_ADDRESS_ONLY_VALIDATOR = sBooleanValidator;
+
/**
* @deprecated Use SIP_ALWAYS or SIP_ADDRESS_ONLY instead. Formerly used to indicate that
* the user should be prompted each time a call is made whether it should be placed using
@@ -2604,6 +2910,9 @@
@Deprecated
public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
+ /** @hide */
+ public static final Validator SIP_ASK_ME_EACH_TIME_VALIDATOR = sBooleanValidator;
+
/**
* Pointer speed setting.
* This is an integer value in a range between -7 and +7, so there are 15 possible values.
@@ -2614,12 +2923,19 @@
*/
public static final String POINTER_SPEED = "pointer_speed";
+ /** @hide */
+ public static final Validator POINTER_SPEED_VALIDATOR =
+ new InclusiveFloatRangeValidator(-7, 7);
+
/**
* Whether lock-to-app will be triggered by long-press on recents.
* @hide
*/
public static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled";
+ /** @hide */
+ public static final Validator LOCK_TO_APP_ENABLED_VALIDATOR = sBooleanValidator;
+
/**
* I am the lolrus.
* <p>
@@ -2629,6 +2945,16 @@
*/
public static final String EGG_MODE = "egg_mode";
+ /** @hide */
+ public static final Validator EGG_MODE_VALIDATOR = sBooleanValidator;
+
+ /**
+ * IMPORTANT: If you add a new public settings you also have to add it to
+ * PUBLIC_SETTINGS below. If the new setting is hidden you have to add
+ * it to PRIVATE_SETTINGS below. Also add a validator that can validate
+ * the setting value. See an example above.
+ */
+
/**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
@@ -2699,17 +3025,200 @@
};
/**
- * These entries are considered common between the personal and the managed profile,
- * since the managed profile doesn't get to change them.
+ * These are all pulbic system settings
+ *
* @hide
*/
- public static final String[] CLONE_TO_MANAGED_PROFILE = {
- DATE_FORMAT,
- HAPTIC_FEEDBACK_ENABLED,
- SOUND_EFFECTS_ENABLED,
- TEXT_SHOW_PASSWORD,
- TIME_12_24
- };
+ public static final Set<String> PUBLIC_SETTINGS = new ArraySet<>();
+ static {
+ PUBLIC_SETTINGS.add(END_BUTTON_BEHAVIOR);
+ PUBLIC_SETTINGS.add(WIFI_USE_STATIC_IP);
+ PUBLIC_SETTINGS.add(WIFI_STATIC_IP);
+ PUBLIC_SETTINGS.add(WIFI_STATIC_GATEWAY);
+ PUBLIC_SETTINGS.add(WIFI_STATIC_NETMASK);
+ PUBLIC_SETTINGS.add(WIFI_STATIC_DNS1);
+ PUBLIC_SETTINGS.add(WIFI_STATIC_DNS2);
+ PUBLIC_SETTINGS.add(BLUETOOTH_DISCOVERABILITY);
+ PUBLIC_SETTINGS.add(BLUETOOTH_DISCOVERABILITY_TIMEOUT);
+ PUBLIC_SETTINGS.add(NEXT_ALARM_FORMATTED);
+ PUBLIC_SETTINGS.add(FONT_SCALE);
+ PUBLIC_SETTINGS.add(DIM_SCREEN);
+ PUBLIC_SETTINGS.add(SCREEN_OFF_TIMEOUT);
+ PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS);
+ PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_MODE);
+ PUBLIC_SETTINGS.add(MODE_RINGER_STREAMS_AFFECTED);
+ PUBLIC_SETTINGS.add(MUTE_STREAMS_AFFECTED);
+ PUBLIC_SETTINGS.add(VIBRATE_ON);
+ PUBLIC_SETTINGS.add(VOLUME_RING);
+ PUBLIC_SETTINGS.add(VOLUME_SYSTEM);
+ PUBLIC_SETTINGS.add(VOLUME_VOICE);
+ PUBLIC_SETTINGS.add(VOLUME_MUSIC);
+ PUBLIC_SETTINGS.add(VOLUME_ALARM);
+ PUBLIC_SETTINGS.add(VOLUME_NOTIFICATION);
+ PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO);
+ PUBLIC_SETTINGS.add(RINGTONE);
+ PUBLIC_SETTINGS.add(NOTIFICATION_SOUND);
+ PUBLIC_SETTINGS.add(ALARM_ALERT);
+ PUBLIC_SETTINGS.add(TEXT_AUTO_REPLACE);
+ PUBLIC_SETTINGS.add(TEXT_AUTO_CAPS);
+ PUBLIC_SETTINGS.add(TEXT_AUTO_PUNCTUATE);
+ PUBLIC_SETTINGS.add(TEXT_SHOW_PASSWORD);
+ PUBLIC_SETTINGS.add(SHOW_GTALK_SERVICE_STATUS);
+ PUBLIC_SETTINGS.add(WALLPAPER_ACTIVITY);
+ PUBLIC_SETTINGS.add(TIME_12_24);
+ PUBLIC_SETTINGS.add(DATE_FORMAT);
+ PUBLIC_SETTINGS.add(SETUP_WIZARD_HAS_RUN);
+ PUBLIC_SETTINGS.add(ACCELEROMETER_ROTATION);
+ PUBLIC_SETTINGS.add(USER_ROTATION);
+ PUBLIC_SETTINGS.add(DTMF_TONE_WHEN_DIALING);
+ PUBLIC_SETTINGS.add(SOUND_EFFECTS_ENABLED);
+ PUBLIC_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
+ PUBLIC_SETTINGS.add(SHOW_WEB_SUGGESTIONS);
+ }
+
+ /**
+ * These are all hidden system settings.
+ *
+ * @hide
+ */
+ public static final Set<String> PRIVATE_SETTINGS = new ArraySet<>();
+ static {
+ PRIVATE_SETTINGS.add(WIFI_USE_STATIC_IP);
+ PRIVATE_SETTINGS.add(END_BUTTON_BEHAVIOR);
+ PRIVATE_SETTINGS.add(ADVANCED_SETTINGS);
+ PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
+ PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
+ PRIVATE_SETTINGS.add(VOLUME_MASTER);
+ PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
+ PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
+ PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
+ PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
+ PRIVATE_SETTINGS.add(MEDIA_BUTTON_RECEIVER);
+ PRIVATE_SETTINGS.add(HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY);
+ PRIVATE_SETTINGS.add(VIBRATE_WHEN_RINGING);
+ PRIVATE_SETTINGS.add(DTMF_TONE_TYPE_WHEN_DIALING);
+ PRIVATE_SETTINGS.add(HEARING_AID);
+ PRIVATE_SETTINGS.add(TTY_MODE);
+ PRIVATE_SETTINGS.add(NOTIFICATION_LIGHT_PULSE);
+ PRIVATE_SETTINGS.add(POINTER_LOCATION);
+ PRIVATE_SETTINGS.add(SHOW_TOUCHES);
+ PRIVATE_SETTINGS.add(WINDOW_ORIENTATION_LISTENER_LOG);
+ PRIVATE_SETTINGS.add(POWER_SOUNDS_ENABLED);
+ PRIVATE_SETTINGS.add(DOCK_SOUNDS_ENABLED);
+ PRIVATE_SETTINGS.add(LOCKSCREEN_SOUNDS_ENABLED);
+ PRIVATE_SETTINGS.add(LOCKSCREEN_DISABLED);
+ PRIVATE_SETTINGS.add(LOW_BATTERY_SOUND);
+ PRIVATE_SETTINGS.add(DESK_DOCK_SOUND);
+ PRIVATE_SETTINGS.add(DESK_UNDOCK_SOUND);
+ PRIVATE_SETTINGS.add(CAR_DOCK_SOUND);
+ PRIVATE_SETTINGS.add(CAR_UNDOCK_SOUND);
+ PRIVATE_SETTINGS.add(LOCK_SOUND);
+ PRIVATE_SETTINGS.add(UNLOCK_SOUND);
+ PRIVATE_SETTINGS.add(SIP_RECEIVE_CALLS);
+ PRIVATE_SETTINGS.add(SIP_CALL_OPTIONS);
+ PRIVATE_SETTINGS.add(SIP_ALWAYS);
+ PRIVATE_SETTINGS.add(SIP_ADDRESS_ONLY);
+ PRIVATE_SETTINGS.add(SIP_ASK_ME_EACH_TIME);
+ PRIVATE_SETTINGS.add(POINTER_SPEED);
+ PRIVATE_SETTINGS.add(LOCK_TO_APP_ENABLED);
+ PRIVATE_SETTINGS.add(EGG_MODE);
+ }
+
+ /**
+ * These are all pulbic system settings
+ *
+ * @hide
+ */
+ public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+ static {
+ VALIDATORS.put(END_BUTTON_BEHAVIOR,END_BUTTON_BEHAVIOR_VALIDATOR);
+ VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR);
+ VALIDATORS.put(BLUETOOTH_DISCOVERABILITY, BLUETOOTH_DISCOVERABILITY_VALIDATOR);
+ VALIDATORS.put(BLUETOOTH_DISCOVERABILITY_TIMEOUT,
+ BLUETOOTH_DISCOVERABILITY_TIMEOUT_VALIDATOR);
+ VALIDATORS.put(NEXT_ALARM_FORMATTED, NEXT_ALARM_FORMATTED_VALIDATOR);
+ VALIDATORS.put(FONT_SCALE, FONT_SCALE_VALIDATOR);
+ VALIDATORS.put(DIM_SCREEN, DIM_SCREEN_VALIDATOR);
+ VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
+ VALIDATORS.put(SCREEN_BRIGHTNESS, SCREEN_BRIGHTNESS_VALIDATOR);
+ VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
+ VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
+ VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR);
+ VALIDATORS.put(VIBRATE_ON, VIBRATE_ON_VALIDATOR);
+ VALIDATORS.put(RINGTONE, RINGTONE_VALIDATOR);
+ VALIDATORS.put(NOTIFICATION_SOUND, NOTIFICATION_SOUND_VALIDATOR);
+ VALIDATORS.put(ALARM_ALERT, ALARM_ALERT_VALIDATOR);
+ VALIDATORS.put(TEXT_AUTO_REPLACE, TEXT_AUTO_REPLACE_VALIDATOR);
+ VALIDATORS.put(TEXT_AUTO_CAPS, TEXT_AUTO_CAPS_VALIDATOR);
+ VALIDATORS.put(TEXT_AUTO_PUNCTUATE, TEXT_AUTO_PUNCTUATE_VALIDATOR);
+ VALIDATORS.put(TEXT_SHOW_PASSWORD, TEXT_SHOW_PASSWORD_VALIDATOR);
+ VALIDATORS.put(SHOW_GTALK_SERVICE_STATUS, SHOW_GTALK_SERVICE_STATUS_VALIDATOR);
+ VALIDATORS.put(WALLPAPER_ACTIVITY, WALLPAPER_ACTIVITY_VALIDATOR);
+ VALIDATORS.put(TIME_12_24, TIME_12_24_VALIDATOR);
+ VALIDATORS.put(DATE_FORMAT, DATE_FORMAT_VALIDATOR);
+ VALIDATORS.put(SETUP_WIZARD_HAS_RUN, SETUP_WIZARD_HAS_RUN_VALIDATOR);
+ VALIDATORS.put(ACCELEROMETER_ROTATION, ACCELEROMETER_ROTATION_VALIDATOR);
+ VALIDATORS.put(USER_ROTATION, USER_ROTATION_VALIDATOR);
+ VALIDATORS.put(DTMF_TONE_WHEN_DIALING, DTMF_TONE_WHEN_DIALING_VALIDATOR);
+ VALIDATORS.put(SOUND_EFFECTS_ENABLED, SOUND_EFFECTS_ENABLED_VALIDATOR);
+ VALIDATORS.put(HAPTIC_FEEDBACK_ENABLED, HAPTIC_FEEDBACK_ENABLED_VALIDATOR);
+ VALIDATORS.put(SHOW_WEB_SUGGESTIONS, SHOW_WEB_SUGGESTIONS_VALIDATOR);
+ VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR);
+ VALIDATORS.put(END_BUTTON_BEHAVIOR, END_BUTTON_BEHAVIOR_VALIDATOR);
+ VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR);
+ VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR);
+ VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
+ VALIDATORS.put(VOLUME_MASTER, VOLUME_MASTER_VALIDATOR);
+ VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
+ VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
+ VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
+ VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
+ VALIDATORS.put(MEDIA_BUTTON_RECEIVER, MEDIA_BUTTON_RECEIVER_VALIDATOR);
+ VALIDATORS.put(HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY,
+ HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY_VALIDATOR);
+ VALIDATORS.put(VIBRATE_WHEN_RINGING, VIBRATE_WHEN_RINGING_VALIDATOR);
+ VALIDATORS.put(DTMF_TONE_TYPE_WHEN_DIALING, DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR);
+ VALIDATORS.put(HEARING_AID, HEARING_AID_VALIDATOR);
+ VALIDATORS.put(TTY_MODE, TTY_MODE_VALIDATOR);
+ VALIDATORS.put(NOTIFICATION_LIGHT_PULSE, NOTIFICATION_LIGHT_PULSE_VALIDATOR);
+ VALIDATORS.put(POINTER_LOCATION, POINTER_LOCATION_VALIDATOR);
+ VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR);
+ VALIDATORS.put(WINDOW_ORIENTATION_LISTENER_LOG,
+ WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR);
+ VALIDATORS.put(LOCKSCREEN_SOUNDS_ENABLED, LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR);
+ VALIDATORS.put(LOCKSCREEN_DISABLED, LOCKSCREEN_DISABLED_VALIDATOR);
+ VALIDATORS.put(SIP_RECEIVE_CALLS, SIP_RECEIVE_CALLS_VALIDATOR);
+ VALIDATORS.put(SIP_CALL_OPTIONS, SIP_CALL_OPTIONS_VALIDATOR);
+ VALIDATORS.put(SIP_ALWAYS, SIP_ALWAYS_VALIDATOR);
+ VALIDATORS.put(SIP_ADDRESS_ONLY, SIP_ADDRESS_ONLY_VALIDATOR);
+ VALIDATORS.put(SIP_ASK_ME_EACH_TIME, SIP_ASK_ME_EACH_TIME_VALIDATOR);
+ VALIDATORS.put(POINTER_SPEED, POINTER_SPEED_VALIDATOR);
+ VALIDATORS.put(LOCK_TO_APP_ENABLED, LOCK_TO_APP_ENABLED_VALIDATOR);
+ VALIDATORS.put(EGG_MODE, EGG_MODE_VALIDATOR);
+ VALIDATORS.put(WIFI_STATIC_IP, WIFI_STATIC_IP_VALIDATOR);
+ VALIDATORS.put(WIFI_STATIC_GATEWAY, WIFI_STATIC_GATEWAY_VALIDATOR);
+ VALIDATORS.put(WIFI_STATIC_NETMASK, WIFI_STATIC_NETMASK_VALIDATOR);
+ VALIDATORS.put(WIFI_STATIC_DNS1, WIFI_STATIC_DNS1_VALIDATOR);
+ VALIDATORS.put(WIFI_STATIC_DNS2, WIFI_STATIC_DNS2_VALIDATOR);
+ }
+
+ /**
+ * These entries are considered common between the personal and the managed profile,
+ * since the managed profile doesn't get to change them.
+ */
+ private static final Set<String> CLONE_TO_MANAGED_PROFILE = new ArraySet<>();
+ static {
+ CLONE_TO_MANAGED_PROFILE.add(DATE_FORMAT);
+ CLONE_TO_MANAGED_PROFILE.add(HAPTIC_FEEDBACK_ENABLED);
+ CLONE_TO_MANAGED_PROFILE.add(SOUND_EFFECTS_ENABLED);
+ CLONE_TO_MANAGED_PROFILE.add(TEXT_SHOW_PASSWORD);
+ CLONE_TO_MANAGED_PROFILE.add(TIME_12_24);
+ }
+
+ /** @hide */
+ public static void getCloneToManagedProfileSettings(Set<String> outKeySet) {
+ outKeySet.addAll(CLONE_TO_MANAGED_PROFILE);
+ }
/**
* When to use Wi-Fi calling
@@ -3099,7 +3608,7 @@
}
/** @hide */
- public static void getMovedKeys(HashSet<String> outKeySet) {
+ public static void getMovedToGlobalSettings(Set<String> outKeySet) {
outKeySet.addAll(MOVED_TO_GLOBAL);
}
@@ -4762,6 +5271,10 @@
public static final String BAR_SERVICE_COMPONENT = "bar_service_component";
/** @hide */
+ public static final String VOLUME_CONTROLLER_SERVICE_COMPONENT
+ = "volume_controller_service_component";
+
+ /** @hide */
public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
/**
@@ -4896,22 +5409,27 @@
/**
* These entries are considered common between the personal and the managed profile,
* since the managed profile doesn't get to change them.
- * @hide
*/
- public static final String[] CLONE_TO_MANAGED_PROFILE = {
- ACCESSIBILITY_ENABLED,
- ALLOW_MOCK_LOCATION,
- ALLOWED_GEOLOCATION_ORIGINS,
- DEFAULT_INPUT_METHOD,
- ENABLED_ACCESSIBILITY_SERVICES,
- ENABLED_INPUT_METHODS,
- LOCATION_MODE,
- LOCATION_PROVIDERS_ALLOWED,
- LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
- SELECTED_INPUT_METHOD_SUBTYPE,
- SELECTED_SPELL_CHECKER,
- SELECTED_SPELL_CHECKER_SUBTYPE
- };
+ private static final Set<String> CLONE_TO_MANAGED_PROFILE = new ArraySet<>();
+ static {
+ CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
+ CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
+ CLONE_TO_MANAGED_PROFILE.add(ALLOWED_GEOLOCATION_ORIGINS);
+ CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
+ CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
+ CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
+ CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
+ CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
+ CLONE_TO_MANAGED_PROFILE.add(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ 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 */
+ public static void getCloneToManagedProfileSettings(Set<String> outKeySet) {
+ outKeySet.addAll(CLONE_TO_MANAGED_PROFILE);
+ }
/**
* Helper method for determining if a location provider is enabled.
@@ -6693,6 +7211,11 @@
MOVED_TO_SECURE.add(Settings.Global.INSTALL_NON_MARKET_APPS);
}
+ /** @hide */
+ public static void getMovedToSecureSettings(Set<String> outKeySet) {
+ outKeySet.addAll(MOVED_TO_SECURE);
+ }
+
/**
* Look up a name in the database.
* @param resolver to access the database with
diff --git a/core/java/android/security/IKeystoreService.aidl b/core/java/android/security/IKeystoreService.aidl
index bf51ed1..ac6bbb7 100644
--- a/core/java/android/security/IKeystoreService.aidl
+++ b/core/java/android/security/IKeystoreService.aidl
@@ -16,6 +16,10 @@
package android.security;
+import android.security.keymaster.ExportResult;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.OperationResult;
import android.security.KeystoreArguments;
/**
@@ -52,4 +56,19 @@
int reset_uid(int uid);
int sync_uid(int sourceUid, int targetUid);
int password_uid(String password, int uid);
+
+ // Keymaster 0.4 methods
+ int addRngEntropy(in byte[] data);
+ int generateKey(String alias, in KeymasterArguments arguments, int uid, int flags,
+ out KeyCharacteristics characteristics);
+ int getKeyCharacteristics(String alias, in byte[] clientId,
+ in byte[] appId, out KeyCharacteristics characteristics);
+ int importKey(String alias, in KeymasterArguments arguments, int format,
+ in byte[] keyData, int uid, int flags, out KeyCharacteristics characteristics);
+ ExportResult exportKey(String alias, int format, in byte[] clientId, in byte[] appId);
+ OperationResult begin(IBinder appToken, String alias, int purpose, boolean pruneable,
+ in KeymasterArguments params, out KeymasterArguments operationParams);
+ OperationResult update(IBinder token, in KeymasterArguments params, in byte[] input);
+ OperationResult finish(IBinder token, in KeymasterArguments params, in byte[] signature);
+ int abort(IBinder handle);
}
diff --git a/core/java/android/midi/MidiDeviceInfo.aidl b/core/java/android/security/keymaster/ExportResult.aidl
similarity index 80%
copy from core/java/android/midi/MidiDeviceInfo.aidl
copy to core/java/android/security/keymaster/ExportResult.aidl
index 59be059..f522355 100644
--- a/core/java/android/midi/MidiDeviceInfo.aidl
+++ b/core/java/android/security/keymaster/ExportResult.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
+/**
+ * Copyright (c) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.security.keymaster;
-parcelable MidiDeviceInfo;
+/* @hide */
+parcelable ExportResult;
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
new file mode 100644
index 0000000..bb44c03
--- /dev/null
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class for handling parceling the return values from keymaster's export operation.
+ * @hide
+ */
+public class ExportResult implements Parcelable {
+ public final int resultCode;
+ public final byte[] exportData;
+
+ public static final Parcelable.Creator<ExportResult> CREATOR = new
+ Parcelable.Creator<ExportResult>() {
+ public ExportResult createFromParcel(Parcel in) {
+ return new ExportResult(in);
+ }
+
+ public ExportResult[] newArray(int length) {
+ return new ExportResult[length];
+ }
+ };
+
+ protected ExportResult(Parcel in) {
+ resultCode = in.readInt();
+ exportData = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(resultCode);
+ out.writeByteArray(exportData);
+ }
+};
diff --git a/core/java/android/midi/MidiDeviceInfo.aidl b/core/java/android/security/keymaster/KeyCharacteristics.aidl
similarity index 79%
copy from core/java/android/midi/MidiDeviceInfo.aidl
copy to core/java/android/security/keymaster/KeyCharacteristics.aidl
index 59be059..15014b1 100644
--- a/core/java/android/midi/MidiDeviceInfo.aidl
+++ b/core/java/android/security/keymaster/KeyCharacteristics.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
+/**
+ * Copyright (c) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.security.keymaster;
-parcelable MidiDeviceInfo;
+/* @hide */
+parcelable KeyCharacteristics;
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
new file mode 100644
index 0000000..b803a1b
--- /dev/null
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * @hide
+ */
+public class KeyCharacteristics implements Parcelable {
+ public KeymasterArguments swEnforced;
+ public KeymasterArguments hwEnforced;
+
+ public static final Parcelable.Creator<KeyCharacteristics> CREATOR = new
+ Parcelable.Creator<KeyCharacteristics>() {
+ public KeyCharacteristics createFromParcel(Parcel in) {
+ return new KeyCharacteristics(in);
+ }
+
+ public KeyCharacteristics[] newArray(int length) {
+ return new KeyCharacteristics[length];
+ }
+ };
+
+ public KeyCharacteristics() {}
+
+ protected KeyCharacteristics(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ swEnforced.writeToParcel(out, flags);
+ hwEnforced.writeToParcel(out, flags);
+ }
+
+ public void readFromParcel(Parcel in) {
+ swEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
+ hwEnforced = KeymasterArguments.CREATOR.createFromParcel(in);
+ }
+}
+
diff --git a/core/java/android/security/keymaster/KeymasterArgument.java b/core/java/android/security/keymaster/KeymasterArgument.java
new file mode 100644
index 0000000..9a1c894
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterArgument.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * Base class for the Java side of a Keymaster tagged argument.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore
+ * and with hardware/libhardware/include/hardware/keymaster_defs.h
+ * @hide
+ */
+abstract class KeymasterArgument implements Parcelable {
+ public final int tag;
+
+ public static final Parcelable.Creator<KeymasterArgument> CREATOR = new
+ Parcelable.Creator<KeymasterArgument>() {
+ public KeymasterArgument createFromParcel(Parcel in) {
+ final int pos = in.dataPosition();
+ final int tag = in.readInt();
+ switch (KeymasterDefs.getTagType(tag)) {
+ case KeymasterDefs.KM_ENUM:
+ case KeymasterDefs.KM_ENUM_REP:
+ case KeymasterDefs.KM_INT:
+ case KeymasterDefs.KM_INT_REP:
+ return new KeymasterIntArgument(tag, in);
+ case KeymasterDefs.KM_LONG:
+ return new KeymasterLongArgument(tag, in);
+ case KeymasterDefs.KM_DATE:
+ return new KeymasterDateArgument(tag, in);
+ case KeymasterDefs.KM_BYTES:
+ case KeymasterDefs.KM_BIGNUM:
+ return new KeymasterBlobArgument(tag, in);
+ case KeymasterDefs.KM_BOOL:
+ return new KeymasterBooleanArgument(tag, in);
+ default:
+ throw new ParcelFormatException("Bad tag: " + tag + " at " + pos);
+ }
+ }
+ public KeymasterArgument[] newArray(int size) {
+ return new KeymasterArgument[size];
+ }
+ };
+
+ protected KeymasterArgument(int tag) {
+ this.tag = tag;
+ }
+
+ /**
+ * Writes the value of this argument, if any, to the provided parcel.
+ */
+ public abstract void writeValue(Parcel out);
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(tag);
+ writeValue(out);
+ }
+}
diff --git a/core/java/android/midi/MidiDeviceInfo.aidl b/core/java/android/security/keymaster/KeymasterArguments.aidl
similarity index 79%
copy from core/java/android/midi/MidiDeviceInfo.aidl
copy to core/java/android/security/keymaster/KeymasterArguments.aidl
index 59be059..7aef5a6 100644
--- a/core/java/android/midi/MidiDeviceInfo.aidl
+++ b/core/java/android/security/keymaster/KeymasterArguments.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
+/**
+ * Copyright (c) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.security.keymaster;
-parcelable MidiDeviceInfo;
+/* @hide */
+parcelable KeymasterArguments;
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
new file mode 100644
index 0000000..b5fd4bd
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -0,0 +1,186 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Utility class for the java side of user specified Keymaster arguments.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore
+ * @hide
+ */
+public class KeymasterArguments implements Parcelable {
+ List<KeymasterArgument> mArguments;
+
+ public static final Parcelable.Creator<KeymasterArguments> CREATOR = new
+ Parcelable.Creator<KeymasterArguments>() {
+ public KeymasterArguments createFromParcel(Parcel in) {
+ return new KeymasterArguments(in);
+ }
+ public KeymasterArguments[] newArray(int size) {
+ return new KeymasterArguments[size];
+ }
+ };
+
+ public KeymasterArguments() {
+ mArguments = new ArrayList<KeymasterArgument>();
+ }
+
+ private KeymasterArguments(Parcel in) {
+ mArguments = in.createTypedArrayList(KeymasterArgument.CREATOR);
+ }
+
+ public void addInt(int tag, int value) {
+ mArguments.add(new KeymasterIntArgument(tag, value));
+ }
+
+ public void addBoolean(int tag) {
+ mArguments.add(new KeymasterBooleanArgument(tag));
+ }
+
+ public void addLong(int tag, long value) {
+ mArguments.add(new KeymasterLongArgument(tag, value));
+ }
+
+ public void addBlob(int tag, byte[] value) {
+ mArguments.add(new KeymasterBlobArgument(tag, value));
+ }
+
+ public void addDate(int tag, Date value) {
+ mArguments.add(new KeymasterDateArgument(tag, value));
+ }
+
+ private KeymasterArgument getArgumentByTag(int tag) {
+ for (KeymasterArgument arg : mArguments) {
+ if (arg.tag == tag) {
+ return arg;
+ }
+ }
+ return null;
+ }
+
+ public boolean containsTag(int tag) {
+ return getArgumentByTag(tag) != null;
+ }
+
+ public int getInt(int tag, int defaultValue) {
+ switch (KeymasterDefs.getTagType(tag)) {
+ case KeymasterDefs.KM_ENUM:
+ case KeymasterDefs.KM_INT:
+ break; // Accepted types
+ case KeymasterDefs.KM_INT_REP:
+ case KeymasterDefs.KM_ENUM_REP:
+ throw new IllegalArgumentException("Repeatable tags must use getInts: " + tag);
+ default:
+ throw new IllegalArgumentException("Tag is not an int type: " + tag);
+ }
+ KeymasterArgument arg = getArgumentByTag(tag);
+ if (arg == null) {
+ return defaultValue;
+ }
+ return ((KeymasterIntArgument) arg).value;
+ }
+
+ public long getLong(int tag, long defaultValue) {
+ if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_LONG) {
+ throw new IllegalArgumentException("Tag is not a long type: " + tag);
+ }
+ KeymasterArgument arg = getArgumentByTag(tag);
+ if (arg == null) {
+ return defaultValue;
+ }
+ return ((KeymasterLongArgument) arg).value;
+ }
+
+ public Date getDate(int tag, Date defaultValue) {
+ if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) {
+ throw new IllegalArgumentException("Tag is not a date type: " + tag);
+ }
+ KeymasterArgument arg = getArgumentByTag(tag);
+ if (arg == null) {
+ return defaultValue;
+ }
+ return ((KeymasterDateArgument) arg).date;
+ }
+
+ public boolean getBoolean(int tag, boolean defaultValue) {
+ if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BOOL) {
+ throw new IllegalArgumentException("Tag is not a boolean type: " + tag);
+ }
+ KeymasterArgument arg = getArgumentByTag(tag);
+ if (arg == null) {
+ return defaultValue;
+ }
+ return true;
+ }
+
+ public byte[] getBlob(int tag, byte[] defaultValue) {
+ switch (KeymasterDefs.getTagType(tag)) {
+ case KeymasterDefs.KM_BYTES:
+ case KeymasterDefs.KM_BIGNUM:
+ break; // Allowed types.
+ default:
+ throw new IllegalArgumentException("Tag is not a blob type: " + tag);
+ }
+ KeymasterArgument arg = getArgumentByTag(tag);
+ if (arg == null) {
+ return defaultValue;
+ }
+ return ((KeymasterBlobArgument) arg).blob;
+ }
+
+ public List<Integer> getInts(int tag) {
+ switch (KeymasterDefs.getTagType(tag)) {
+ case KeymasterDefs.KM_INT_REP:
+ case KeymasterDefs.KM_ENUM_REP:
+ break; // Allowed types.
+ default:
+ throw new IllegalArgumentException("Tag is not a repeating type: " + tag);
+ }
+ List<Integer> values = new ArrayList<Integer>();
+ for (KeymasterArgument arg : mArguments) {
+ if (arg.tag == tag) {
+ values.add(((KeymasterIntArgument) arg).value);
+ }
+ }
+ return values;
+ }
+
+ public int size() {
+ return mArguments.size();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeTypedList(mArguments);
+ }
+
+ public void readFromParcel(Parcel in) {
+ in.readTypedList(mArguments, KeymasterArgument.CREATOR);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java
new file mode 100644
index 0000000..27f1153
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+class KeymasterBlobArgument extends KeymasterArgument {
+ public final byte[] blob;
+
+ public KeymasterBlobArgument(int tag, byte[] blob) {
+ super(tag);
+ this.blob = blob;
+ }
+
+ public KeymasterBlobArgument(int tag, Parcel in) {
+ super(tag);
+ blob = in.createByteArray();
+ }
+
+ @Override
+ public void writeValue(Parcel out) {
+ out.writeByteArray(blob);
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
new file mode 100644
index 0000000..8e17db4
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+class KeymasterBooleanArgument extends KeymasterArgument {
+
+ // Boolean arguments are always true if they exist and false if they don't.
+ public final boolean value = true;
+
+ public KeymasterBooleanArgument(int tag) {
+ super(tag);
+ }
+
+ public KeymasterBooleanArgument(int tag, Parcel in) {
+ super(tag);
+ }
+
+ @Override
+ public void writeValue(Parcel out) {
+ // Do nothing, value is implicit.
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java
new file mode 100644
index 0000000..e8f4055
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterDateArgument.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Date;
+
+/**
+ * @hide
+ */
+class KeymasterDateArgument extends KeymasterArgument {
+ public final Date date;
+
+ public KeymasterDateArgument(int tag, Date date) {
+ super(tag);
+ this.date = date;
+ }
+
+ public KeymasterDateArgument(int tag, Parcel in) {
+ super(tag);
+ date = new Date(in.readLong());
+ }
+
+ @Override
+ public void writeValue(Parcel out) {
+ out.writeLong(date.getTime());
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
new file mode 100644
index 0000000..88cad79
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -0,0 +1,227 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+/**
+ * Class tracking all the keymaster enum values needed for the binder API to keystore.
+ * This must be kept in sync with hardware/libhardware/include/hardware/keymaster_defs.h
+ * See keymaster_defs.h for detailed descriptions of each constant.
+ * @hide
+ */
+public final class KeymasterDefs {
+
+ private KeymasterDefs() {}
+
+ // Tag types.
+ public static final int KM_INVALID = 0 << 28;
+ public static final int KM_ENUM = 1 << 28;
+ public static final int KM_ENUM_REP = 2 << 28;
+ public static final int KM_INT = 3 << 28;
+ public static final int KM_INT_REP = 4 << 28;
+ public static final int KM_LONG = 5 << 28;
+ public static final int KM_DATE = 6 << 28;
+ public static final int KM_BOOL = 7 << 28;
+ public static final int KM_BIGNUM = 8 << 28;
+ public static final int KM_BYTES = 9 << 28;
+
+ // Tag values.
+ public static final int KM_TAG_INVALID = KM_INVALID | 0;
+ public static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
+ public static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
+ public static final int KM_TAG_KEY_SIZE = KM_INT | 3;
+ public static final int KM_TAG_BLOCK_MODE = KM_ENUM | 4;
+ public static final int KM_TAG_DIGEST = KM_ENUM | 5;
+ public static final int KM_TAG_MAC_LENGTH = KM_INT | 6;
+ public static final int KM_TAG_PADDING = KM_ENUM | 7;
+ public static final int KM_TAG_RETURN_UNAUTHED = KM_BOOL | 8;
+ public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 9;
+
+ public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
+ public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
+ public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 705;
+
+ public static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_LONG | 200;
+ public static final int KM_TAG_DSA_GENERATOR = KM_BIGNUM | 201;
+ public static final int KM_TAG_DSA_P = KM_BIGNUM | 202;
+ public static final int KM_TAG_DSA_Q = KM_BIGNUM | 203;
+ public static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
+ public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
+ public static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
+ public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS = KM_INT | 403;
+ public static final int KM_TAG_MAX_USES_PER_BOOT = KM_INT | 404;
+
+ public static final int KM_TAG_ALL_USERS = KM_BOOL | 500;
+ public static final int KM_TAG_USER_ID = KM_INT | 501;
+ public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 502;
+ public static final int KM_TAG_USER_AUTH_ID = KM_INT_REP | 503;
+ public static final int KM_TAG_AUTH_TIMEOUT = KM_INT | 504;
+
+ public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
+ public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
+
+ public static final int KM_TAG_APPLICATION_DATA = KM_BYTES | 700;
+ public static final int KM_TAG_CREATION_DATETIME = KM_DATE | 701;
+ public static final int KM_TAG_ORIGIN = KM_ENUM | 702;
+ public static final int KM_TAG_ROLLBACK_RESISTANT = KM_BOOL | 703;
+ public static final int KM_TAG_ROOT_OF_TRUST = KM_BYTES | 704;
+
+ public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
+ public static final int KM_TAG_NONCE = KM_BYTES | 1001;
+ public static final int KM_TAG_CHUNK_LENGTH = KM_INT | 1002;
+
+ // Algorithm values.
+ public static final int KM_ALGORITHM_RSA = 1;
+ public static final int KM_ALGORITHM_DSA = 2;
+ public static final int KM_ALGORITHM_ECDSA = 3;
+ public static final int KM_ALGORITHM_ECIES = 4;
+ public static final int KM_ALGORITHM_AES = 32;
+ public static final int KM_ALGORITHM_3DES = 33;
+ public static final int KM_ALGORITHM_SKIPJACK = 34;
+ public static final int KM_ALGORITHM_MARS = 48;
+ public static final int KM_ALGORITHM_RC6 = 49;
+ public static final int KM_ALGORITHM_SERPENT = 50;
+ public static final int KM_ALGORITHM_TWOFISH = 51;
+ public static final int KM_ALGORITHM_IDEA = 52;
+ public static final int KM_ALGORITHM_RC5 = 53;
+ public static final int KM_ALGORITHM_CAST5 = 54;
+ public static final int KM_ALGORITHM_BLOWFISH = 55;
+ public static final int KM_ALGORITHM_RC4 = 64;
+ public static final int KM_ALGORITHM_CHACHA20 = 65;
+ public static final int KM_ALGORITHM_HMAC = 128;
+
+ // Block modes.
+ public static final int KM_MODE_FIRST_UNAUTHENTICATED = 1;
+ public static final int KM_MODE_ECB = KM_MODE_FIRST_UNAUTHENTICATED;
+ public static final int KM_MODE_CBC = 2;
+ public static final int KM_MODE_CBC_CTS = 3;
+ public static final int KM_MODE_CTR = 4;
+ public static final int KM_MODE_OFB = 5;
+ public static final int KM_MODE_CFB = 6;
+ public static final int KM_MODE_XTS = 7;
+ public static final int KM_MODE_FIRST_AUTHENTICATED = 32;
+ public static final int KM_MODE_GCM = KM_MODE_FIRST_AUTHENTICATED;
+ public static final int KM_MODE_OCB = 33;
+ public static final int KM_MODE_CCM = 34;
+ public static final int KM_MODE_FIRST_MAC = 128;
+ public static final int KM_MODE_CMAC = KM_MODE_FIRST_MAC;
+ public static final int KM_MODE_POLY1305 = 129;
+
+ // Padding modes.
+ public static final int KM_PAD_NONE = 1;
+ public static final int KM_PAD_RSA_OAEP = 2;
+ public static final int KM_PAD_RSA_PSS = 3;
+ public static final int KM_PAD_RSA_PKCS1_1_5_ENCRYPT = 4;
+ public static final int KM_PAD_RSA_PKCS1_1_5_SIGN = 5;
+ public static final int KM_PAD_ANSI_X923 = 32;
+ public static final int KM_PAD_ISO_10126 = 33;
+ public static final int KM_PAD_ZERO = 64;
+ public static final int KM_PAD_PKCS7 = 65;
+ public static final int KM_PAD_ISO_7816_4 = 66;
+
+ // Digest modes.
+ public static final int KM_DIGEST_NONE = 0;
+ public static final int KM_DIGEST_MD5 = 1;
+ public static final int KM_DIGEST_SHA1 = 2;
+ public static final int KM_DIGEST_SHA_2_224 = 3;
+ public static final int KM_DIGEST_SHA_2_256 = 4;
+ public static final int KM_DIGEST_SHA_2_384 = 5;
+ public static final int KM_DIGEST_SHA_2_512 = 6;
+ public static final int KM_DIGEST_SHA_3_256 = 7;
+ public static final int KM_DIGEST_SHA_3_384 = 8;
+ public static final int KM_DIGEST_SHA_3_512 = 9;
+
+ // Key origins.
+ public static final int KM_ORIGIN_HARDWARE = 0;
+ public static final int KM_ORIGIN_SOFTWARE = 1;
+ public static final int KM_ORIGIN_IMPORTED = 2;
+
+ // Key usability requirements.
+ public static final int KM_BLOB_STANDALONE = 0;
+ public static final int KM_BLOB_REQUIRES_FILE_SYSTEM = 1;
+
+ // Operation Purposes.
+ public static final int KM_PURPOSE_ENCRYPT = 0;
+ public static final int KM_PURPOSE_DECRYPT = 1;
+ public static final int KM_PURPOSE_SIGN = 2;
+ public static final int KM_PURPOSE_VERIFY = 3;
+
+ // Key formats.
+ public static final int KM_KEY_FORMAT_X509 = 0;
+ public static final int KM_KEY_FORMAT_PKCS8 = 1;
+ public static final int KM_KEY_FORMAT_PKCS12 = 2;
+ public static final int KM_KEY_FORMAT_RAW = 3;
+
+ // Error codes.
+ public static final int KM_ERROR_OK = 0;
+ public static final int KM_ERROR_ROOT_OF_TRUST_ALREADY_SET = -1;
+ public static final int KM_ERROR_UNSUPPORTED_PURPOSE = -2;
+ public static final int KM_ERROR_INCOMPATIBLE_PURPOSE = -3;
+ public static final int KM_ERROR_UNSUPPORTED_ALGORITHM = -4;
+ public static final int KM_ERROR_INCOMPATIBLE_ALGORITHM = -5;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6;
+ public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7;
+ public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8;
+ public static final int KM_ERROR_UNSUPPORTED_TAG_LENGTH = -9;
+ public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10;
+ public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11;
+ public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12;
+ public static final int KM_ERROR_INCOMPATIBLE_DIGEST = -13;
+ public static final int KM_ERROR_INVALID_EXPIRATION_TIME = -14;
+ public static final int KM_ERROR_INVALID_USER_ID = -15;
+ public static final int KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT = -16;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_FORMAT = -17;
+ public static final int KM_ERROR_INCOMPATIBLE_KEY_FORMAT = -18;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19;
+ public static final int KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20;
+ public static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
+ public static final int KM_ERROR_KEY_EXPORT_OPTIONS_INVALID = -22;
+ public static final int KM_ERROR_DELEGATION_NOT_ALLOWED = -23;
+ public static final int KM_ERROR_KEY_NOT_YET_VALID = -24;
+ public static final int KM_ERROR_KEY_EXPIRED = -25;
+ public static final int KM_ERROR_KEY_USER_NOT_AUTHENTICATED = -26;
+ public static final int KM_ERROR_OUTPUT_PARAMETER_NULL = -27;
+ public static final int KM_ERROR_INVALID_OPERATION_HANDLE = -28;
+ public static final int KM_ERROR_INSUFFICIENT_BUFFER_SPACE = -29;
+ public static final int KM_ERROR_VERIFICATION_FAILED = -30;
+ public static final int KM_ERROR_TOO_MANY_OPERATIONS = -31;
+ public static final int KM_ERROR_UNEXPECTED_NULL_POINTER = -32;
+ public static final int KM_ERROR_INVALID_KEY_BLOB = -33;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED = -34;
+ public static final int KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED = -35;
+ public static final int KM_ERROR_IMPORTED_KEY_NOT_SIGNED = -36;
+ public static final int KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED = -37;
+ public static final int KM_ERROR_INVALID_ARGUMENT = -38;
+ public static final int KM_ERROR_UNSUPPORTED_TAG = -39;
+ public static final int KM_ERROR_INVALID_TAG = -40;
+ public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED = -41;
+ public static final int KM_ERROR_INVALID_RESCOPING = -42;
+ public static final int KM_ERROR_INVALID_DSA_PARAMS = -43;
+ public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44;
+ public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED = -45;
+ public static final int KM_ERROR_OPERATION_CANCELLED = -46;
+ public static final int KM_ERROR_CONCURRENT_ACCESS_CONFLICT = -47;
+ public static final int KM_ERROR_SECURE_HW_BUSY = -48;
+ public static final int KM_ERROR_SECURE_HW_COMMUNICATION_FAILED = -49;
+ public static final int KM_ERROR_UNSUPPORTED_EC_FIELD = -50;
+ public static final int KM_ERROR_UNIMPLEMENTED = -100;
+ public static final int KM_ERROR_VERSION_MISMATCH = -101;
+ public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
+
+ public static int getTagType(int tag) {
+ return tag & (0xF << 28);
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java
new file mode 100644
index 0000000..71797ae
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterIntArgument.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+class KeymasterIntArgument extends KeymasterArgument {
+ public final int value;
+
+ public KeymasterIntArgument(int tag, int value) {
+ super(tag);
+ this.value = value;
+ }
+
+ public KeymasterIntArgument(int tag, Parcel in) {
+ super(tag);
+ value = in.readInt();
+ }
+
+ @Override
+ public void writeValue(Parcel out) {
+ out.writeInt(value);
+ }
+}
diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java
new file mode 100644
index 0000000..781b1ab
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterLongArgument.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+class KeymasterLongArgument extends KeymasterArgument {
+ public final long value;
+
+ public KeymasterLongArgument(int tag, long value) {
+ super(tag);
+ this.value = value;
+ }
+
+ public KeymasterLongArgument(int tag, Parcel in) {
+ super(tag);
+ value = in.readLong();
+ }
+
+ @Override
+ public void writeValue(Parcel out) {
+ out.writeLong(value);
+ }
+}
diff --git a/core/java/android/midi/MidiDeviceInfo.aidl b/core/java/android/security/keymaster/OperationResult.aidl
similarity index 80%
copy from core/java/android/midi/MidiDeviceInfo.aidl
copy to core/java/android/security/keymaster/OperationResult.aidl
index 59be059..699e8d0 100644
--- a/core/java/android/midi/MidiDeviceInfo.aidl
+++ b/core/java/android/security/keymaster/OperationResult.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2014, The Android Open Source Project
+/**
+ * Copyright (c) 2015, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.security.keymaster;
-parcelable MidiDeviceInfo;
+/* @hide */
+parcelable OperationResult;
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
new file mode 100644
index 0000000..ad54c96
--- /dev/null
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keymaster;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * Class for handling the parceling of return values from keymaster crypto operations
+ * (begin/update/finish).
+ * @hide
+ */
+public class OperationResult implements Parcelable {
+ public final int resultCode;
+ public final IBinder token;
+ public final int inputConsumed;
+ public final byte[] output;
+
+ public static final Parcelable.Creator<OperationResult> CREATOR = new
+ Parcelable.Creator<OperationResult>() {
+ public OperationResult createFromParcel(Parcel in) {
+ return new OperationResult(in);
+ }
+
+ public OperationResult[] newArray(int length) {
+ return new OperationResult[length];
+ }
+ };
+
+ protected OperationResult(Parcel in) {
+ resultCode = in.readInt();
+ token = in.readStrongBinder();
+ inputConsumed = in.readInt();
+ output = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(resultCode);
+ out.writeStrongBinder(token);
+ out.writeInt(inputConsumed);
+ out.writeByteArray(output);
+ }
+}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 3c57dda..df4d7e0 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -18,6 +18,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.AlarmManager;
@@ -382,7 +385,7 @@
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
- public void setContentView(int layoutResID) {
+ public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
}
@@ -442,7 +445,8 @@
*
* @return The view if found or null otherwise.
*/
- public View findViewById(int id) {
+ @Nullable
+ public View findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
@@ -1037,10 +1041,10 @@
protected void dump(final FileDescriptor fd, PrintWriter pw, final String[] args) {
DumpUtils.dumpAsync(mHandler, new Dump() {
@Override
- public void dump(PrintWriter pw) {
+ public void dump(PrintWriter pw, String prefix) {
dumpOnHandler(fd, pw, args);
}
- }, pw, 1000);
+ }, pw, "", 1000);
}
/** @hide */
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 3d39b18..0860153 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -77,6 +77,14 @@
*/
public static final int INTERRUPTION_FILTER_NONE = 3;
+ /** {@link #getCurrentInterruptionFilter() Interruption filter} constant - returned when
+ * the value is unavailable for any reason. For example, before the notification listener
+ * is connected.
+ *
+ * {@see #onListenerConnected()}
+ */
+ public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
+
/** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
* should disable notification sound, vibrating and other visual or aural effects.
* This does not change the interruption filter, only the effects. **/
@@ -473,15 +481,16 @@
* <p>
* Listen for updates using {@link #onInterruptionFilterChanged(int)}.
*
- * @return One of the INTERRUPTION_FILTER_ constants, or 0 on errors.
+ * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
+ * unavailable.
*/
public final int getCurrentInterruptionFilter() {
- if (!isBound()) return 0;
+ if (!isBound()) return INTERRUPTION_FILTER_UNKNOWN;
try {
return getNotificationInterface().getInterruptionFilterFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
- return 0;
+ return INTERRUPTION_FILTER_UNKNOWN;
}
}
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 9f9c312..a8c0c4c 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -17,11 +17,13 @@
package android.service.voice;
import android.content.Intent;
+import android.os.Bundle;
/**
* @hide
*/
oneway interface IVoiceInteractionSession {
+ void handleAssist(in Bundle assistData);
void taskStarted(in Intent intent, int taskId);
void taskFinished(in Intent intent, int taskId);
void closeSystemDialogs();
diff --git a/core/java/android/service/voice/IVoiceInteractionSessionService.aidl b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
index 2519442..7f8158f 100644
--- a/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
@@ -24,5 +24,5 @@
* @hide
*/
oneway interface IVoiceInteractionSessionService {
- void newSession(IBinder token, in Bundle args);
+ void newSession(IBinder token, in Bundle args, int startFlags);
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 65e6988..54a3a0a 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -70,6 +70,12 @@
*/
public static final String SERVICE_META_DATA = "android.voice_interaction";
+ /**
+ * Flag for use with {@link #startSession}: request that the session be started with
+ * assist data from the currently focused activity.
+ */
+ public static final int START_WITH_ASSIST = 1<<0;
+
IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
@Override public void ready() {
mHandler.sendEmptyMessage(MSG_READY);
@@ -136,16 +142,21 @@
* Initiate the execution of a new {@link android.service.voice.VoiceInteractionSession}.
* @param args Arbitrary arguments that will be propagated to the session.
*/
- public void startSession(Bundle args) {
+ public void startSession(Bundle args, int flags) {
if (mSystemService == null) {
throw new IllegalStateException("Not available until onReady() is called");
}
try {
- mSystemService.startSession(mInterface, args);
+ mSystemService.startSession(mInterface, args, flags);
} catch (RemoteException e) {
}
}
+ /** @hide */
+ public void startSession(Bundle args) {
+ startSession(args, 0);
+ }
+
@Override
public void onCreate() {
super.onCreate();
@@ -163,8 +174,8 @@
/**
* Called during service initialization to tell you when the system is ready
* to receive interaction from it. You should generally do initialization here
- * rather than in {@link #onCreate()}. Methods such as {@link #startSession(Bundle)} and
- * {@link #createAlwaysOnHotwordDetector(String, Locale, android.service.voice.AlwaysOnHotwordDetector.Callback)}
+ * rather than in {@link #onCreate}. Methods such as {@link #startSession} and
+ * {@link #createAlwaysOnHotwordDetector}
* will not be operational until this point.
*/
public void onReady() {
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index e6e9413..ebc7507 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -99,6 +99,10 @@
mParseError = "No sessionService specified";
return;
}
+ if (mRecognitionService == null) {
+ mParseError = "No recognitionService specified";
+ return;
+ }
/* Not yet time
if (mRecognitionService == null) {
mParseError = "No recogitionService specified";
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 19d14bf..a3a2ca1 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -50,7 +50,6 @@
import java.lang.ref.WeakReference;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
/**
* An active voice interaction session, providing a facility for the implementation
@@ -91,7 +90,6 @@
final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
final Insets mTmpInsets = new Insets();
- final int[] mTmpLocation = new int[2];
final WeakReference<VoiceInteractionSession> mWeakRef
= new WeakReference<VoiceInteractionSession>(this);
@@ -153,6 +151,12 @@
final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
@Override
+ public void handleAssist(Bundle assistBundle) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_HANDLE_ASSIST,
+ assistBundle));
+ }
+
+ @Override
public void taskStarted(Intent intent, int taskId) {
mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_TASK_STARTED,
taskId, intent));
@@ -279,6 +283,7 @@
static final int MSG_TASK_FINISHED = 101;
static final int MSG_CLOSE_SYSTEM_DIALOGS = 102;
static final int MSG_DESTROY = 103;
+ static final int MSG_HANDLE_ASSIST = 104;
class MyCallbacks implements HandlerCaller.Callback, SoftInputWindow.Callback {
@Override
@@ -341,6 +346,10 @@
if (DEBUG) Log.d(TAG, "doDestroy");
doDestroy();
break;
+ case MSG_HANDLE_ASSIST:
+ if (DEBUG) Log.d(TAG, "onHandleAssist: " + (Bundle)msg.obj);
+ onHandleAssist((Bundle) msg.obj);
+ break;
}
}
@@ -441,10 +450,11 @@
}
}
- void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args) {
+ void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args,
+ int startFlags) {
mSystemService = service;
mToken = token;
- onCreate(args);
+ onCreate(args, startFlags);
}
void doDestroy() {
@@ -585,12 +595,7 @@
}
}
- /**
- * Initiatize a new session.
- *
- * @param args The arguments that were supplied to
- * {@link VoiceInteractionService#startSession VoiceInteractionService.startSession}.
- */
+ /** @hide */
public void onCreate(Bundle args) {
mTheme = mTheme != 0 ? mTheme
: com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession;
@@ -598,14 +603,26 @@
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
mCallbacks, this, mDispatcherState,
- WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.TOP, true);
+ WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
initViews();
- mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
+ mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
mWindow.setToken(mToken);
}
/**
+ * Initiatize a new session.
+ *
+ * @param args The arguments that were supplied to
+ * {@link VoiceInteractionService#startSession VoiceInteractionService.startSession}.
+ * @param startFlags The start flags originally provided to
+ * {@link VoiceInteractionService#startSession VoiceInteractionService.startSession}.
+ */
+ public void onCreate(Bundle args, int startFlags) {
+ onCreate(args);
+ }
+
+ /**
* Last callback to the session as it is being finished.
*/
public void onDestroy() {
@@ -622,10 +639,13 @@
mContentFrame.removeAllViews();
mContentFrame.addView(view, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
+ ViewGroup.LayoutParams.MATCH_PARENT));
}
+ public void onHandleAssist(Bundle assistBundle) {
+ }
+
public boolean onKeyDown(int keyCode, KeyEvent event) {
return false;
}
@@ -657,19 +677,19 @@
/**
* Compute the interesting insets into your UI. The default implementation
- * uses the entire window frame as the insets. The default touchable
- * insets are {@link Insets#TOUCHABLE_INSETS_FRAME}.
+ * sets {@link Insets#contentInsets outInsets.contentInsets.top} to the height
+ * of the window, meaning it should not adjust content underneath. The default touchable
+ * insets are {@link Insets#TOUCHABLE_INSETS_FRAME}, meaning it consumes all touch
+ * events within its window frame.
*
* @param outInsets Fill in with the current UI insets.
*/
public void onComputeInsets(Insets outInsets) {
- int[] loc = mTmpLocation;
- View decor = getWindow().getWindow().getDecorView();
- decor.getLocationInWindow(loc);
- outInsets.contentInsets.top = 0;
outInsets.contentInsets.left = 0;
- outInsets.contentInsets.right = 0;
outInsets.contentInsets.bottom = 0;
+ outInsets.contentInsets.right = 0;
+ View decor = getWindow().getWindow().getDecorView();
+ outInsets.contentInsets.top = decor.getHeight();
outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_FRAME;
outInsets.touchableRegion.setEmpty();
}
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
index e793849..008d55f 100644
--- a/core/java/android/service/voice/VoiceInteractionSessionService.java
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -40,9 +40,9 @@
VoiceInteractionSession mSession;
IVoiceInteractionSessionService mInterface = new IVoiceInteractionSessionService.Stub() {
- public void newSession(IBinder token, Bundle args) {
- mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(MSG_NEW_SESSION,
- token, args));
+ public void newSession(IBinder token, Bundle args, int startFlags) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(MSG_NEW_SESSION,
+ startFlags, token, args));
}
};
@@ -54,7 +54,7 @@
SomeArgs args = (SomeArgs)msg.obj;
switch (msg.what) {
case MSG_NEW_SESSION:
- doNewSession((IBinder)args.arg1, (Bundle)args.arg2);
+ doNewSession((IBinder)args.arg1, (Bundle)args.arg2, args.argi1);
break;
}
}
@@ -76,7 +76,7 @@
return mInterface.asBinder();
}
- void doNewSession(IBinder token, Bundle args) {
+ void doNewSession(IBinder token, Bundle args, int startFlags) {
if (mSession != null) {
mSession.doDestroy();
mSession = null;
@@ -84,7 +84,7 @@
mSession = onNewSession(args);
try {
mSystemService.deliverNewSession(token, mSession.mSession, mSession.mInteractor);
- mSession.doCreate(mSystemService, token, args);
+ mSession.doCreate(mSystemService, token, args, startFlags);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 06e9ce0..f0ad951 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -15,6 +15,7 @@
*/
package android.speech.tts;
+import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
@@ -884,7 +885,7 @@
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addSpeech(String text, String packagename, int resourceId) {
+ public int addSpeech(String text, String packagename, @RawRes int resourceId) {
synchronized (mStartLock) {
mUtterances.put(text, makeResourceUri(packagename, resourceId));
return SUCCESS;
@@ -993,7 +994,7 @@
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addEarcon(String earcon, String packagename, int resourceId) {
+ public int addEarcon(String earcon, String packagename, @RawRes int resourceId) {
synchronized(mStartLock) {
mEarcons.put(earcon, makeResourceUri(packagename, resourceId));
return SUCCESS;
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 06df683..7ce44e1 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -26,6 +26,7 @@
import libcore.util.EmptyArray;
import java.lang.reflect.Array;
+import java.util.IdentityHashMap;
/**
* This is the class for text whose content and markup can both be changed.
@@ -68,6 +69,7 @@
mSpanStarts = EmptyArray.INT;
mSpanEnds = EmptyArray.INT;
mSpanFlags = EmptyArray.INT;
+ mSpanMax = EmptyArray.INT;
if (text instanceof Spanned) {
Spanned sp = (Spanned) text;
@@ -94,6 +96,7 @@
setSpan(false, spans[i], st, en, fl);
}
+ restoreInvariants();
}
}
@@ -147,9 +150,12 @@
if (mGapLength < 1)
new Exception("mGapLength < 1").printStackTrace();
- for (int i = 0; i < mSpanCount; i++) {
- if (mSpanStarts[i] > mGapStart) mSpanStarts[i] += delta;
- if (mSpanEnds[i] > mGapStart) mSpanEnds[i] += delta;
+ if (mSpanCount != 0) {
+ for (int i = 0; i < mSpanCount; i++) {
+ if (mSpanStarts[i] > mGapStart) mSpanStarts[i] += delta;
+ if (mSpanEnds[i] > mGapStart) mSpanEnds[i] += delta;
+ }
+ calcMax(treeRoot());
}
}
@@ -167,35 +173,38 @@
System.arraycopy(mText, where + mGapLength - overlap, mText, mGapStart, overlap);
}
- // XXX be more clever
- for (int i = 0; i < mSpanCount; i++) {
- int start = mSpanStarts[i];
- int end = mSpanEnds[i];
+ // TODO: be more clever (although the win really isn't that big)
+ if (mSpanCount != 0) {
+ for (int i = 0; i < mSpanCount; i++) {
+ int start = mSpanStarts[i];
+ int end = mSpanEnds[i];
- if (start > mGapStart)
- start -= mGapLength;
- if (start > where)
- start += mGapLength;
- else if (start == where) {
- int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
-
- if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ if (start > mGapStart)
+ start -= mGapLength;
+ if (start > where)
start += mGapLength;
- }
+ else if (start == where) {
+ int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
- if (end > mGapStart)
- end -= mGapLength;
- if (end > where)
- end += mGapLength;
- else if (end == where) {
- int flag = (mSpanFlags[i] & END_MASK);
+ if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ start += mGapLength;
+ }
- if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ if (end > mGapStart)
+ end -= mGapLength;
+ if (end > where)
end += mGapLength;
- }
+ else if (end == where) {
+ int flag = (mSpanFlags[i] & END_MASK);
- mSpanStarts[i] = start;
- mSpanEnds[i] = end;
+ if (flag == POINT || (atEnd && flag == PARAGRAPH))
+ end += mGapLength;
+ }
+
+ mSpanStarts[i] = start;
+ mSpanEnds[i] = end;
+ }
+ calcMax(treeRoot());
}
mGapStart = where;
@@ -243,6 +252,9 @@
sendSpanRemoved(what, ostart, oend);
}
+ if (mIndexOfSpan != null) {
+ mIndexOfSpan.clear();
+ }
}
// Documentation from interface
@@ -277,12 +289,39 @@
return append(String.valueOf(text));
}
+ // Returns true if a node was removed (so we can restart search from root)
+ private boolean removeSpansForChange(int start, int end, boolean textIsRemoved, int i) {
+ if ((i & 1) != 0) {
+ // internal tree node
+ if (resolveGap(mSpanMax[i]) >= start &&
+ removeSpansForChange(start, end, textIsRemoved, leftChild(i))) {
+ return true;
+ }
+ }
+ if (i < mSpanCount) {
+ if ((mSpanFlags[i] & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
+ mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
+ mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength &&
+ // The following condition indicates that the span would become empty
+ (textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
+ mIndexOfSpan.remove(mSpans[i]);
+ removeSpan(i);
+ return true;
+ }
+ return resolveGap(mSpanStarts[i]) <= end && (i & 1) != 0 &&
+ removeSpansForChange(start, end, textIsRemoved, rightChild(i));
+ }
+ return false;
+ }
+
private void change(int start, int end, CharSequence cs, int csStart, int csEnd) {
// Can be negative
final int replacedLength = end - start;
final int replacementLength = csEnd - csStart;
final int nbNewChars = replacementLength - replacedLength;
+ boolean changed = false;
for (int i = mSpanCount - 1; i >= 0; i--) {
int spanStart = mSpanStarts[i];
if (spanStart > mGapStart)
@@ -309,8 +348,10 @@
break;
}
- if (spanStart != ost || spanEnd != oen)
+ if (spanStart != ost || spanEnd != oen) {
setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i]);
+ changed = true;
+ }
}
int flags = 0;
@@ -320,6 +361,9 @@
else if (spanEnd == end + nbNewChars) flags |= SPAN_END_AT_END;
mSpanFlags[i] |= flags;
}
+ if (changed) {
+ restoreInvariants();
+ }
moveGapTo(end);
@@ -331,23 +375,10 @@
// The removal pass needs to be done before the gap is updated in order to broadcast the
// correct previous positions to the correct intersecting SpanWatchers
if (replacedLength > 0) { // no need for span fixup on pure insertion
- // A for loop will not work because the array is being modified
- // Do not iterate in reverse to keep the SpanWatchers notified in ordering
- // Also, a removed SpanWatcher should not get notified of removed spans located
- // further in the span array.
- int i = 0;
- while (i < mSpanCount) {
- if ((mSpanFlags[i] & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
- mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
- mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength &&
- // This condition indicates that the span would become empty
- (textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
- removeSpan(i);
- continue; // do not increment i, spans will be shifted left in the array
- }
-
- i++;
+ while (mSpanCount > 0 &&
+ removeSpansForChange(start, end, textIsRemoved, treeRoot())) {
+ // keep deleting spans as needed, and restart from root after every deletion
+ // because deletion can invalidate an index.
}
}
@@ -360,6 +391,7 @@
TextUtils.getChars(cs, csStart, csEnd, mText, start);
if (replacedLength > 0) { // no need for span fixup on pure insertion
+ // TODO potential optimization: only update bounds on intersecting spans
final boolean atEnd = (mGapStart + mGapLength == mText.length);
for (int i = 0; i < mSpanCount; i++) {
@@ -371,10 +403,10 @@
mSpanEnds[i] = updatedIntervalBound(mSpanEnds[i], start, nbNewChars, endFlag,
atEnd, textIsRemoved);
}
+ // TODO potential optimization: only fix up invariants when bounds actually changed
+ restoreInvariants();
}
- mSpanCountBeforeAdd = mSpanCount;
-
if (cs instanceof Spanned) {
Spanned sp = (Spanned) cs;
Object[] spans = sp.getSpans(csStart, csEnd, Object.class);
@@ -389,9 +421,10 @@
// Add span only if this object is not yet used as a span in this string
if (getSpanStart(spans[i]) < 0) {
setSpan(false, spans[i], st - csStart + start, en - csStart + start,
- sp.getSpanFlags(spans[i]));
+ sp.getSpanFlags(spans[i]) | SPAN_ADDED);
}
}
+ restoreInvariants();
}
}
@@ -427,6 +460,7 @@
return offset;
}
+ // Note: caller is responsible for removing the mIndexOfSpan entry.
private void removeSpan(int i) {
Object object = mSpans[i];
@@ -444,8 +478,12 @@
mSpanCount--;
+ invalidateIndex(i);
mSpans[mSpanCount] = null;
+ // Invariants must be restored before sending span removed notifications.
+ restoreInvariants();
+
sendSpanRemoved(object, start, end);
}
@@ -496,10 +534,12 @@
change(start, end, tb, tbstart, tbend);
if (adjustSelection) {
+ boolean changed = false;
if (selectionStart > start && selectionStart < end) {
final int offset = (selectionStart - start) * newLen / origLen;
selectionStart = start + offset;
+ changed = true;
setSpan(false, Selection.SELECTION_START, selectionStart, selectionStart,
Spanned.SPAN_POINT_POINT);
}
@@ -507,9 +547,13 @@
final int offset = (selectionEnd - start) * newLen / origLen;
selectionEnd = start + offset;
+ changed = true;
setSpan(false, Selection.SELECTION_END, selectionEnd, selectionEnd,
Spanned.SPAN_POINT_POINT);
}
+ if (changed) {
+ restoreInvariants();
+ }
}
sendTextChanged(textWatchers, start, origLen, newLen);
@@ -536,12 +580,15 @@
}
private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) {
- for (int i = 0; i < mSpanCountBeforeAdd; i++) {
+ for (int i = 0; i < mSpanCount; i++) {
+ int spanFlags = mSpanFlags[i];
+
+ // This loop handles only modified (not added) spans.
+ if ((spanFlags & SPAN_ADDED) != 0) continue;
int spanStart = mSpanStarts[i];
int spanEnd = mSpanEnds[i];
if (spanStart > mGapStart) spanStart -= mGapLength;
if (spanEnd > mGapStart) spanEnd -= mGapLength;
- int spanFlags = mSpanFlags[i];
int newReplaceEnd = replaceEnd + nbNewChars;
boolean spanChanged = false;
@@ -588,13 +635,17 @@
mSpanFlags[i] &= ~SPAN_START_END_MASK;
}
- // The spans starting at mIntermediateSpanCount were added from the replacement text
- for (int i = mSpanCountBeforeAdd; i < mSpanCount; i++) {
- int spanStart = mSpanStarts[i];
- int spanEnd = mSpanEnds[i];
- if (spanStart > mGapStart) spanStart -= mGapLength;
- if (spanEnd > mGapStart) spanEnd -= mGapLength;
- sendSpanAdded(mSpans[i], spanStart, spanEnd);
+ // Handle added spans
+ for (int i = 0; i < mSpanCount; i++) {
+ int spanFlags = mSpanFlags[i];
+ if ((spanFlags & SPAN_ADDED) != 0) {
+ mSpanFlags[i] &= ~SPAN_ADDED;
+ int spanStart = mSpanStarts[i];
+ int spanEnd = mSpanEnds[i];
+ if (spanStart > mGapStart) spanStart -= mGapLength;
+ if (spanEnd > mGapStart) spanEnd -= mGapLength;
+ sendSpanAdded(mSpans[i], spanStart, spanEnd);
+ }
}
}
@@ -607,6 +658,9 @@
setSpan(true, what, start, end, flags);
}
+ // Note: if send is false, then it is the caller's responsibility to restore
+ // invariants. If send is false and the span already exists, then this method
+ // will not change the index of any spans.
private void setSpan(boolean send, Object what, int start, int end, int flags) {
checkRange("setSpan", start, end);
@@ -661,8 +715,10 @@
int count = mSpanCount;
Object[] spans = mSpans;
- for (int i = 0; i < count; i++) {
- if (spans[i] == what) {
+ if (mIndexOfSpan != null) {
+ Integer index = mIndexOfSpan.get(what);
+ if (index != null) {
+ int i = index;
int ostart = mSpanStarts[i];
int oend = mSpanEnds[i];
@@ -675,7 +731,10 @@
mSpanEnds[i] = end;
mSpanFlags[i] = flags;
- if (send) sendSpanChanged(what, ostart, oend, nstart, nend);
+ if (send) {
+ restoreInvariants();
+ sendSpanChanged(what, ostart, oend, nstart, nend);
+ }
return;
}
@@ -685,43 +744,48 @@
mSpanStarts = GrowingArrayUtils.append(mSpanStarts, mSpanCount, start);
mSpanEnds = GrowingArrayUtils.append(mSpanEnds, mSpanCount, end);
mSpanFlags = GrowingArrayUtils.append(mSpanFlags, mSpanCount, flags);
+ invalidateIndex(mSpanCount);
mSpanCount++;
+ // Make sure there is enough room for empty interior nodes.
+ // This magic formula computes the size of the smallest perfect binary
+ // tree no smaller than mSpanCount.
+ int sizeOfMax = 2 * treeRoot() + 1;
+ if (mSpanMax.length < sizeOfMax) {
+ mSpanMax = new int[sizeOfMax];
+ }
- if (send) sendSpanAdded(what, nstart, nend);
+ if (send) {
+ restoreInvariants();
+ sendSpanAdded(what, nstart, nend);
+ }
}
/**
* Remove the specified markup object from the buffer.
*/
public void removeSpan(Object what) {
- for (int i = mSpanCount - 1; i >= 0; i--) {
- if (mSpans[i] == what) {
- removeSpan(i);
- return;
- }
+ if (mIndexOfSpan == null) return;
+ Integer i = mIndexOfSpan.remove(what);
+ if (i != null) {
+ removeSpan(i.intValue());
}
}
/**
+ * Return externally visible offset given offset into gapped buffer.
+ */
+ private int resolveGap(int i) {
+ return i > mGapStart ? i - mGapLength : i;
+ }
+
+ /**
* Return the buffer offset of the beginning of the specified
* markup object, or -1 if it is not attached to this buffer.
*/
public int getSpanStart(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanStarts[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
+ if (mIndexOfSpan == null) return -1;
+ Integer i = mIndexOfSpan.get(what);
+ return i == null ? -1 : resolveGap(mSpanStarts[i]);
}
/**
@@ -729,21 +793,9 @@
* markup object, or -1 if it is not attached to this buffer.
*/
public int getSpanEnd(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- int where = mSpanEnds[i];
-
- if (where > mGapStart)
- where -= mGapLength;
-
- return where;
- }
- }
-
- return -1;
+ if (mIndexOfSpan == null) return -1;
+ Integer i = mIndexOfSpan.get(what);
+ return i == null ? -1 : resolveGap(mSpanEnds[i]);
}
/**
@@ -751,16 +803,9 @@
* markup object, or 0 if it is not attached to this buffer.
*/
public int getSpanFlags(Object what) {
- int count = mSpanCount;
- Object[] spans = mSpans;
-
- for (int i = count - 1; i >= 0; i--) {
- if (spans[i] == what) {
- return mSpanFlags[i];
- }
- }
-
- return 0;
+ if (mIndexOfSpan == null) return 0;
+ Integer i = mIndexOfSpan.get(what);
+ return i == null ? 0 : mSpanFlags[i];
}
/**
@@ -770,59 +815,84 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) {
- if (kind == null) return ArrayUtils.emptyArray(kind);
+ if (kind == null || mSpanCount == 0) return ArrayUtils.emptyArray(kind);
+ int count = countSpans(queryStart, queryEnd, kind, treeRoot());
+ if (count == 0) {
+ return ArrayUtils.emptyArray(kind);
+ }
- int spanCount = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int[] flags = mSpanFlags;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
+ // Safe conversion, but requires a suppressWarning
+ T[] ret = (T[]) Array.newInstance(kind, count);
+ getSpansRec(queryStart, queryEnd, kind, treeRoot(), ret, 0);
+ return ret;
+ }
+ private int countSpans(int queryStart, int queryEnd, Class kind, int i) {
int count = 0;
- T[] ret = null;
- T ret1 = null;
-
- for (int i = 0; i < spanCount; i++) {
- int spanStart = starts[i];
- if (spanStart > gapstart) {
- spanStart -= gaplen;
+ if ((i & 1) != 0) {
+ // internal tree node
+ int left = leftChild(i);
+ int spanMax = mSpanMax[left];
+ if (spanMax > mGapStart) {
+ spanMax -= mGapLength;
}
- if (spanStart > queryEnd) {
- continue;
+ if (spanMax >= queryStart) {
+ count = countSpans(queryStart, queryEnd, kind, left);
}
-
- int spanEnd = ends[i];
- if (spanEnd > gapstart) {
- spanEnd -= gaplen;
+ }
+ if (i < mSpanCount) {
+ int spanStart = mSpanStarts[i];
+ if (spanStart > mGapStart) {
+ spanStart -= mGapLength;
}
- if (spanEnd < queryStart) {
- continue;
- }
-
- if (spanStart != spanEnd && queryStart != queryEnd) {
- if (spanStart == queryEnd)
- continue;
- if (spanEnd == queryStart)
- continue;
- }
-
- // Expensive test, should be performed after the previous tests
- if (!kind.isInstance(spans[i])) continue;
-
- if (count == 0) {
- // Safe conversion thanks to the isInstance test above
- ret1 = (T) spans[i];
- count++;
- } else {
- if (count == 1) {
- // Safe conversion, but requires a suppressWarning
- ret = (T[]) Array.newInstance(kind, spanCount - i + 1);
- ret[0] = ret1;
+ if (spanStart <= queryEnd) {
+ int spanEnd = mSpanEnds[i];
+ if (spanEnd > mGapStart) {
+ spanEnd -= mGapLength;
}
+ if (spanEnd >= queryStart &&
+ (spanStart == spanEnd || queryStart == queryEnd ||
+ (spanStart != queryEnd && spanEnd != queryStart)) &&
+ kind.isInstance(mSpans[i])) {
+ count++;
+ }
+ if ((i & 1) != 0) {
+ count += countSpans(queryStart, queryEnd, kind, rightChild(i));
+ }
+ }
+ }
+ return count;
+ }
- int prio = flags[i] & SPAN_PRIORITY;
+ @SuppressWarnings("unchecked")
+ private <T> int getSpansRec(int queryStart, int queryEnd, Class<T> kind,
+ int i, T[] ret, int count) {
+ if ((i & 1) != 0) {
+ // internal tree node
+ int left = leftChild(i);
+ int spanMax = mSpanMax[left];
+ if (spanMax > mGapStart) {
+ spanMax -= mGapLength;
+ }
+ if (spanMax >= queryStart) {
+ count = getSpansRec(queryStart, queryEnd, kind, left, ret, count);
+ }
+ }
+ if (i >= mSpanCount) return count;
+ int spanStart = mSpanStarts[i];
+ if (spanStart > mGapStart) {
+ spanStart -= mGapLength;
+ }
+ if (spanStart <= queryEnd) {
+ int spanEnd = mSpanEnds[i];
+ if (spanEnd > mGapStart) {
+ spanEnd -= mGapLength;
+ }
+ if (spanEnd >= queryStart &&
+ (spanStart == spanEnd || queryStart == queryEnd ||
+ (spanStart != queryEnd && spanEnd != queryStart)) &&
+ kind.isInstance(mSpans[i])) {
+ int prio = mSpanFlags[i] & SPAN_PRIORITY;
if (prio != 0) {
int j;
@@ -836,32 +906,18 @@
System.arraycopy(ret, j, ret, j + 1, count - j);
// Safe conversion thanks to the isInstance test above
- ret[j] = (T) spans[i];
- count++;
+ ret[j] = (T) mSpans[i];
} else {
// Safe conversion thanks to the isInstance test above
- ret[count++] = (T) spans[i];
+ ret[count] = (T) mSpans[i];
}
+ count++;
+ }
+ if (count < ret.length && (i & 1) != 0) {
+ count = getSpansRec(queryStart, queryEnd, kind, rightChild(i), ret, count);
}
}
-
- if (count == 0) {
- return ArrayUtils.emptyArray(kind);
- }
- if (count == 1) {
- // Safe conversion, but requires a suppressWarning
- ret = (T[]) Array.newInstance(kind, 1);
- ret[0] = ret1;
- return ret;
- }
- if (count == ret.length) {
- return ret;
- }
-
- // Safe conversion, but requires a suppressWarning
- T[] nret = (T[]) Array.newInstance(kind, count);
- System.arraycopy(ret, 0, nret, 0, count);
- return nret;
+ return count;
}
/**
@@ -870,30 +926,31 @@
* begins or ends.
*/
public int nextSpanTransition(int start, int limit, Class kind) {
- int count = mSpanCount;
- Object[] spans = mSpans;
- int[] starts = mSpanStarts;
- int[] ends = mSpanEnds;
- int gapstart = mGapStart;
- int gaplen = mGapLength;
-
+ if (mSpanCount == 0) return limit;
if (kind == null) {
kind = Object.class;
}
+ return nextSpanTransitionRec(start, limit, kind, treeRoot());
+ }
- for (int i = 0; i < count; i++) {
- int st = starts[i];
- int en = ends[i];
-
- if (st > gapstart)
- st -= gaplen;
- if (en > gapstart)
- en -= gaplen;
-
- if (st > start && st < limit && kind.isInstance(spans[i]))
+ private int nextSpanTransitionRec(int start, int limit, Class kind, int i) {
+ if ((i & 1) != 0) {
+ // internal tree node
+ int left = leftChild(i);
+ if (resolveGap(mSpanMax[left]) > start) {
+ limit = nextSpanTransitionRec(start, limit, kind, left);
+ }
+ }
+ if (i < mSpanCount) {
+ int st = resolveGap(mSpanStarts[i]);
+ int en = resolveGap(mSpanEnds[i]);
+ if (st > start && st < limit && kind.isInstance(mSpans[i]))
limit = st;
- if (en > start && en < limit && kind.isInstance(spans[i]))
+ if (en > start && en < limit && kind.isInstance(mSpans[i]))
limit = en;
+ if (st < limit && (i & 1) != 0) {
+ limit = nextSpanTransitionRec(start, limit, kind, rightChild(i));
+ }
}
return limit;
@@ -1339,6 +1396,118 @@
return hash;
}
+ // Primitives for treating span list as binary tree
+
+ // The spans (along with start and end offsets and flags) are stored in linear arrays sorted
+ // by start offset. For fast searching, there is a binary search structure imposed over these
+ // arrays. This structure is inorder traversal of a perfect binary tree, a slightly unusual
+ // but advantageous approach.
+
+ // The value-containing nodes are indexed 0 <= i < n (where n = mSpanCount), thus preserving
+ // logic that accesses the values as a contiguous array. Other balanced binary tree approaches
+ // (such as a complete binary tree) would require some shuffling of node indices.
+
+ // Basic properties of this structure: For a perfect binary tree of height m:
+ // The tree has 2^(m+1) - 1 total nodes.
+ // The root of the tree has index 2^m - 1.
+ // All leaf nodes have even index, all interior nodes odd.
+ // The height of a node of index i is the number of trailing ones in i's binary representation.
+ // The left child of a node i of height h is i - 2^(h - 1).
+ // The right child of a node i of height h is i + 2^(h - 1).
+
+ // Note that for arbitrary n, interior nodes of this tree may be >= n. Thus, the general
+ // structure of a recursive traversal of node i is:
+ // * traverse left child if i is an interior node
+ // * process i if i < n
+ // * traverse right child if i is an interior node and i < n
+
+ private int treeRoot() {
+ return Integer.highestOneBit(mSpanCount) - 1;
+ }
+
+ // (i+1) & ~i is equal to 2^(the number of trailing ones in i)
+ private static int leftChild(int i) {
+ return i - (((i + 1) & ~i) >> 1);
+ }
+
+ private static int rightChild(int i) {
+ return i + (((i + 1) & ~i) >> 1);
+ }
+
+ // The span arrays are also augmented by an mSpanMax[] array that represents an interval tree
+ // over the binary tree structure described above. For each node, the mSpanMax[] array contains
+ // the maximum value of mSpanEnds of that node and its descendants. Thus, traversals can
+ // easily reject subtrees that contain no spans overlapping the area of interest.
+
+ // Note that mSpanMax[] also has a valid valuefor interior nodes of index >= n, but which have
+ // descendants of index < n. In these cases, it simply represents the maximum span end of its
+ // descendants. This is a consequence of the perfect binary tree structure.
+ private int calcMax(int i) {
+ int max = 0;
+ if ((i & 1) != 0) {
+ // internal tree node
+ max = calcMax(leftChild(i));
+ }
+ if (i < mSpanCount) {
+ max = Math.max(max, mSpanEnds[i]);
+ if ((i & 1) != 0) {
+ max = Math.max(max, calcMax(rightChild(i)));
+ }
+ }
+ mSpanMax[i] = max;
+ return max;
+ }
+
+ // restores binary interval tree invariants after any mutation of span structure
+ private void restoreInvariants() {
+ if (mSpanCount == 0) return;
+
+ // invariant 1: span starts are nondecreasing
+
+ // This is a simple insertion sort because we expect it to be mostly sorted.
+ for (int i = 1; i < mSpanCount; i++) {
+ if (mSpanStarts[i] < mSpanStarts[i - 1]) {
+ Object span = mSpans[i];
+ int start = mSpanStarts[i];
+ int end = mSpanEnds[i];
+ int flags = mSpanFlags[i];
+ int j = i;
+ do {
+ mSpans[j] = mSpans[j - 1];
+ mSpanStarts[j] = mSpanStarts[j - 1];
+ mSpanEnds[j] = mSpanEnds[j - 1];
+ mSpanFlags[j] = mSpanFlags[j - 1];
+ j--;
+ } while (j > 0 && start < mSpanStarts[j - 1]);
+ mSpans[j] = span;
+ mSpanStarts[j] = start;
+ mSpanEnds[j] = end;
+ mSpanFlags[j] = flags;
+ invalidateIndex(j);
+ }
+ }
+
+ // invariant 2: max is max span end for each node and its descendants
+ calcMax(treeRoot());
+
+ // invariant 3: mIndexOfSpan maps spans back to indices
+ if (mIndexOfSpan == null) {
+ mIndexOfSpan = new IdentityHashMap<Object, Integer>();
+ }
+ for (int i = mLowWaterMark; i < mSpanCount; i++) {
+ Integer existing = mIndexOfSpan.get(mSpans[i]);
+ if (existing == null || existing != i) {
+ mIndexOfSpan.put(mSpans[i], i);
+ }
+ }
+ mLowWaterMark = Integer.MAX_VALUE;
+ }
+
+ // Call this on any update to mSpans[], so that mIndexOfSpan can be updated
+ private void invalidateIndex(int i) {
+ mLowWaterMark = Math.min(i, mLowWaterMark);
+ }
+
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
private InputFilter[] mFilters = NO_FILTERS;
@@ -1349,9 +1518,11 @@
private Object[] mSpans;
private int[] mSpanStarts;
private int[] mSpanEnds;
+ private int[] mSpanMax; // see calcMax() for an explanation of what this array stores
private int[] mSpanFlags;
private int mSpanCount;
- private int mSpanCountBeforeAdd;
+ private IdentityHashMap<Object, Integer> mIndexOfSpan;
+ private int mLowWaterMark; // indices below this have not been touched
// TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned}
private static final int MARK = 1;
@@ -1363,6 +1534,7 @@
private static final int START_SHIFT = 4;
// These bits are not (currently) used by SPANNED flags
+ private static final int SPAN_ADDED = 0x800;
private static final int SPAN_START_AT_START = 0x1000;
private static final int SPAN_START_AT_END = 0x2000;
private static final int SPAN_END_AT_START = 0x4000;
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 48bb5dd..1bb35f6 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -16,6 +16,7 @@
package android.text;
+import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
@@ -457,7 +458,7 @@
* @param str the string to be examined
* @return true if str is null or zero length
*/
- public static boolean isEmpty(CharSequence str) {
+ public static boolean isEmpty(@Nullable CharSequence str) {
if (str == null || str.length() == 0)
return true;
else
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index d0ed871..ac98e8a 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -28,9 +28,11 @@
import java.util.Formatter;
import java.util.GregorianCalendar;
import java.util.Locale;
+import java.util.TimeZone;
import libcore.icu.DateIntervalFormat;
import libcore.icu.LocaleData;
+import libcore.icu.RelativeDateTimeFormatter;
/**
* This class contains various date-related utilities for creating text for things like
@@ -242,6 +244,8 @@
/**
* Returns a string describing the elapsed time since startTime.
+ * <p>
+ * The minimum timespan to report is set to {@link #MINUTE_IN_MILLIS}.
* @param startTime some time in the past.
* @return a String object containing the elapsed time.
* @see #getRelativeTimeSpanString(long, long, long)
@@ -289,69 +293,8 @@
*/
public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
int flags) {
- Resources r = Resources.getSystem();
- boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;
-
- boolean past = (now >= time);
- long duration = Math.abs(now - time);
-
- int resId;
- long count;
- if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) {
- count = duration / SECOND_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_seconds_ago;
- } else {
- resId = com.android.internal.R.plurals.num_seconds_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_seconds;
- } else {
- resId = com.android.internal.R.plurals.in_num_seconds;
- }
- }
- } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
- count = duration / MINUTE_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_minutes_ago;
- } else {
- resId = com.android.internal.R.plurals.num_minutes_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_minutes;
- } else {
- resId = com.android.internal.R.plurals.in_num_minutes;
- }
- }
- } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) {
- count = duration / HOUR_IN_MILLIS;
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_hours_ago;
- } else {
- resId = com.android.internal.R.plurals.num_hours_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_hours;
- } else {
- resId = com.android.internal.R.plurals.in_num_hours;
- }
- }
- } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- return getRelativeDayString(r, time, now);
- } else {
- // We know that we won't be showing the time, so it is safe to pass
- // in a null context.
- return formatDateRange(null, time, time, flags);
- }
-
- String format = r.getQuantityString(resId, (int) count);
- return String.format(format, count);
+ return RelativeDateTimeFormatter.getRelativeTimeSpanString(Locale.getDefault(),
+ TimeZone.getDefault(), time, now, minResolution, flags);
}
/**
@@ -360,8 +303,8 @@
* <p>
* Example output strings for the US date format.
* <ul>
- * <li>3 mins ago, 10:15 AM</li>
- * <li>yesterday, 12:20 PM</li>
+ * <li>3 min. ago, 10:15 AM</li>
+ * <li>Yesterday, 12:20 PM</li>
* <li>Dec 12, 4:12 AM</li>
* <li>11/14/2007, 8:20 AM</li>
* </ul>
@@ -374,86 +317,19 @@
* @param transitionResolution the elapsed time (in milliseconds) at which
* to stop reporting relative measurements. Elapsed times greater
* than this resolution will default to normal date formatting.
- * For example, will transition from "6 days ago" to "Dec 12"
+ * For example, will transition from "7 days ago" to "Dec 12"
* when using {@link #WEEK_IN_MILLIS}.
*/
public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution,
long transitionResolution, int flags) {
- Resources r = Resources.getSystem();
-
- long now = System.currentTimeMillis();
- long duration = Math.abs(now - time);
-
- // getRelativeTimeSpanString() doesn't correctly format relative dates
- // above a week or exact dates below a day, so clamp
- // transitionResolution as needed.
- if (transitionResolution > WEEK_IN_MILLIS) {
- transitionResolution = WEEK_IN_MILLIS;
- } else if (transitionResolution < DAY_IN_MILLIS) {
- transitionResolution = DAY_IN_MILLIS;
+ // Same reason as in formatDateRange() to explicitly indicate 12- or 24-hour format.
+ if ((flags & (FORMAT_SHOW_TIME | FORMAT_12HOUR | FORMAT_24HOUR)) == FORMAT_SHOW_TIME) {
+ flags |= DateFormat.is24HourFormat(c) ? FORMAT_24HOUR : FORMAT_12HOUR;
}
- CharSequence timeClause = formatDateRange(c, time, time, FORMAT_SHOW_TIME);
-
- String result;
- if (duration < transitionResolution) {
- CharSequence relativeClause = getRelativeTimeSpanString(time, now, minResolution, flags);
- result = r.getString(com.android.internal.R.string.relative_time, relativeClause, timeClause);
- } else {
- CharSequence dateClause = getRelativeTimeSpanString(c, time, false);
- result = r.getString(com.android.internal.R.string.date_time, dateClause, timeClause);
- }
-
- return result;
- }
-
- /**
- * Returns a string describing a day relative to the current day. For example if the day is
- * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
- * if the day is in 2 weeks it returns "in 14 days".
- *
- * @param r the resources
- * @param day the relative day to describe in UTC milliseconds
- * @param today the current time in UTC milliseconds
- */
- private static final String getRelativeDayString(Resources r, long day, long today) {
- Locale locale = r.getConfiguration().locale;
- if (locale == null) {
- locale = Locale.getDefault();
- }
-
- // TODO: use TimeZone.getOffset instead.
- Time startTime = new Time();
- startTime.set(day);
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
-
- Time currentTime = new Time();
- currentTime.set(today);
- int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
-
- int days = Math.abs(currentDay - startDay);
- boolean past = (today > day);
-
- // TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
- if (days == 1) {
- if (past) {
- return LocaleData.get(locale).yesterday;
- } else {
- return LocaleData.get(locale).tomorrow;
- }
- } else if (days == 0) {
- return LocaleData.get(locale).today;
- }
-
- int resId;
- if (past) {
- resId = com.android.internal.R.plurals.num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
-
- String format = r.getQuantityString(resId, days);
- return String.format(format, days);
+ return RelativeDateTimeFormatter.getRelativeDateTimeString(Locale.getDefault(),
+ TimeZone.getDefault(), time, System.currentTimeMillis(), minResolution,
+ transitionResolution, flags);
}
private static void initFormatStrings() {
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 3d6f8e6..856dd0b 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -16,6 +16,7 @@
package android.text.style;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -110,7 +111,7 @@
mSource = uri.toString();
}
- public ImageSpan(Context context, int resourceId) {
+ public ImageSpan(Context context, @DrawableRes int resourceId) {
this(context, resourceId, ALIGN_BOTTOM);
}
@@ -118,7 +119,7 @@
* @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
* {@link DynamicDrawableSpan#ALIGN_BASELINE}.
*/
- public ImageSpan(Context context, int resourceId, int verticalAlignment) {
+ public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment) {
super(verticalAlignment);
mContext = context;
mResourceId = resourceId;
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index f95fb49..70dfe7f 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -21,7 +21,6 @@
import android.content.res.TypedArray;
import android.graphics.Path;
import android.util.AttributeSet;
-import android.util.FloatMath;
/**
* A PathMotion that generates a curved path along an arc on an imaginary circle containing
@@ -257,7 +256,7 @@
}
if (newArcDistance2 != 0) {
float ratio2 = newArcDistance2 / arcDist2;
- float ratio = FloatMath.sqrt(ratio2);
+ float ratio = (float) Math.sqrt(ratio2);
ex = dx + (ratio * (ex - dx));
ey = dy + (ratio * (ey - dy));
}
diff --git a/core/java/android/transition/CircularPropagation.java b/core/java/android/transition/CircularPropagation.java
index 51beb51..1e44cfa 100644
--- a/core/java/android/transition/CircularPropagation.java
+++ b/core/java/android/transition/CircularPropagation.java
@@ -16,7 +16,6 @@
package android.transition;
import android.graphics.Rect;
-import android.util.FloatMath;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -87,9 +86,9 @@
epicenterY = Math.round(loc[1] + (sceneRoot.getHeight() / 2)
+ sceneRoot.getTranslationY());
}
- float distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY);
- float maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
- float distanceFraction = distance/maxDistance;
+ double distance = distance(viewCenterX, viewCenterY, epicenterX, epicenterY);
+ double maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
+ double distanceFraction = distance/maxDistance;
long duration = transition.getDuration();
if (duration < 0) {
@@ -99,9 +98,9 @@
return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction);
}
- private static float distance(float x1, float y1, float x2, float y2) {
- float x = x2 - x1;
- float y = y2 - y1;
- return FloatMath.sqrt((x * x) + (y * y));
+ private static double distance(float x1, float y1, float x2, float y2) {
+ double x = x2 - x1;
+ double y = y2 - y1;
+ return Math.hypot(x, y);
}
}
diff --git a/core/java/android/transition/Explode.java b/core/java/android/transition/Explode.java
index 0ccdf15..788676a 100644
--- a/core/java/android/transition/Explode.java
+++ b/core/java/android/transition/Explode.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.FloatMath;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
@@ -143,32 +142,29 @@
int centerX = bounds.centerX();
int centerY = bounds.centerY();
- float xVector = centerX - focalX;
- float yVector = centerY - focalY;
+ double xVector = centerX - focalX;
+ double yVector = centerY - focalY;
if (xVector == 0 && yVector == 0) {
// Random direction when View is centered on focal View.
- xVector = (float) (Math.random() * 2) - 1;
- yVector = (float) (Math.random() * 2) - 1;
+ xVector = (Math.random() * 2) - 1;
+ yVector = (Math.random() * 2) - 1;
}
- float vectorSize = calculateDistance(xVector, yVector);
+ double vectorSize = Math.hypot(xVector, yVector);
xVector /= vectorSize;
yVector /= vectorSize;
- float maxDistance =
+ double maxDistance =
calculateMaxDistance(sceneRoot, focalX - sceneRootX, focalY - sceneRootY);
- outVector[0] = Math.round(maxDistance * xVector);
- outVector[1] = Math.round(maxDistance * yVector);
+ outVector[0] = (int) Math.round(maxDistance * xVector);
+ outVector[1] = (int) Math.round(maxDistance * yVector);
}
- private static float calculateMaxDistance(View sceneRoot, int focalX, int focalY) {
+ private static double calculateMaxDistance(View sceneRoot, int focalX, int focalY) {
int maxX = Math.max(focalX, sceneRoot.getWidth() - focalX);
int maxY = Math.max(focalY, sceneRoot.getHeight() - focalY);
- return calculateDistance(maxX, maxY);
+ return Math.hypot(maxX, maxY);
}
- private static float calculateDistance(float x, float y) {
- return FloatMath.sqrt((x * x) + (y * y));
- }
}
diff --git a/core/java/android/transition/PatternPathMotion.java b/core/java/android/transition/PatternPathMotion.java
index a609df6..773c387 100644
--- a/core/java/android/transition/PatternPathMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -23,7 +23,6 @@
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
-import android.util.FloatMath;
import android.util.PathParser;
/**
@@ -119,7 +118,7 @@
mTempMatrix.setTranslate(-startX, -startY);
float dx = endX - startX;
float dy = endY - startY;
- float distance = distance(dx, dy);
+ float distance = (float) Math.hypot(dx, dy);
float scale = 1 / distance;
mTempMatrix.postScale(scale, scale);
double angle = Math.atan2(dy, dx);
@@ -130,9 +129,9 @@
@Override
public Path getPath(float startX, float startY, float endX, float endY) {
- float dx = endX - startX;
- float dy = endY - startY;
- float length = distance(dx, dy);
+ double dx = endX - startX;
+ double dy = endY - startY;
+ float length = (float) Math.hypot(dx, dy);
double angle = Math.atan2(dy, dx);
mTempMatrix.setScale(length, length);
@@ -143,7 +142,4 @@
return path;
}
- private static float distance(float x, float y) {
- return FloatMath.sqrt((x * x) + (y * y));
- }
}
diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java
index ad6c2dd..5dd1fff 100644
--- a/core/java/android/transition/SidePropagation.java
+++ b/core/java/android/transition/SidePropagation.java
@@ -16,7 +16,6 @@
package android.transition;
import android.graphics.Rect;
-import android.util.FloatMath;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 2705bcf..c942042 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1762,7 +1762,17 @@
runAnimators();
}
- boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
+ /**
+ * Returns whether transition values have changed between the start scene and the end scene
+ * (thus determining whether animation is required). The default implementation compares the
+ * property values returned from {@link #getTransitionProperties()}, or all property values if
+ * {@code getTransitionProperties()} returns null. Subclasses may override this method to
+ * provide logic more specific to their transition implementation.
+ *
+ * @param oldValues the first set of values, may be {@code null}
+ * @param newValues the second set of values, may be {@code null}
+ */
+ protected boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
boolean valuesChanged = false;
// if oldValues null, then transition didn't care to stash values,
// and won't get canceled
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 8779229..26dca43 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -182,7 +182,7 @@
return visibility == View.VISIBLE && parent != null;
}
- private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
+ private static VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
TransitionValues endValues) {
final VisibilityInfo visInfo = new VisibilityInfo();
visInfo.visibilityChange = false;
@@ -484,7 +484,7 @@
}
@Override
- boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
+ protected boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
if (oldValues == null && newValues == null) {
return false;
}
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index a6466fc..3aa3447 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -102,7 +102,7 @@
str = new FileOutputStream(mBaseName);
} catch (FileNotFoundException e) {
File parent = mBaseName.getParentFile();
- if (!parent.mkdir()) {
+ if (!parent.mkdirs()) {
throw new IOException("Couldn't create directory " + mBaseName);
}
FileUtils.setPermissions(
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index c855e57..d0e5b9e 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -62,6 +62,13 @@
public static final int DENSITY_HIGH = 240;
/**
+ * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
+ * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
+ * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
+ */
+ public static final int DENSITY_280 = 280;
+
+ /**
* Standard quantized DPI for extra-high-density screens.
*/
public static final int DENSITY_XHIGH = 320;
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 74d4245..98aaa81 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -16,6 +16,8 @@
package android.util;
+import android.annotation.AnyRes;
+
/**
* Container for a dynamically typed data value. Primarily used with
* {@link android.content.res.Resources} for holding resource values.
@@ -178,6 +180,7 @@
public int assetCookie;
/** If Value came from a resource, this holds the corresponding resource id. */
+ @AnyRes
public int resourceId;
/** If Value came from a resource, these are the configurations for which
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index ae4b60f..a018138 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -17,6 +17,8 @@
package android.view;
+import android.annotation.StringRes;
+
/**
* Represents a contextual mode of the user interface. Action modes can be used to provide
* alternative interaction modes and replace parts of the normal UI until finished.
@@ -93,7 +95,7 @@
* @see #setTitle(CharSequence)
* @see #setCustomView(View)
*/
- public abstract void setTitle(int resId);
+ public abstract void setTitle(@StringRes int resId);
/**
* Set the subtitle of the action mode. This method will have no visible effect if
@@ -115,7 +117,7 @@
* @see #setSubtitle(CharSequence)
* @see #setCustomView(View)
*/
- public abstract void setSubtitle(int resId);
+ public abstract void setSubtitle(@StringRes int resId);
/**
* Set whether or not the title/subtitle display for this action mode
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f41afcf..c8149d9 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -141,6 +141,19 @@
private long mFrameIntervalNanos;
/**
+ * Contains information about the current frame for jank-tracking,
+ * mainly timings of key events along with a bit of metadata about
+ * view tree state
+ *
+ * TODO: Is there a better home for this? Currently Choreographer
+ * is the only one with CALLBACK_ANIMATION start time, hence why this
+ * resides here.
+ *
+ * @hide
+ */
+ FrameInfo mFrameInfo = new FrameInfo();
+
+ /**
* Callback type: Input callback. Runs first.
* @hide
*/
@@ -513,6 +526,7 @@
return; // no work to do
}
+ long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
@@ -541,12 +555,18 @@
return;
}
+ mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
+ mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
+
+ mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
+
+ mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
if (DEBUG) {
diff --git a/core/java/android/view/ContextMenu.java b/core/java/android/view/ContextMenu.java
index decabcb..85fe421 100644
--- a/core/java/android/view/ContextMenu.java
+++ b/core/java/android/view/ContextMenu.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.widget.AdapterView;
@@ -44,7 +46,7 @@
* @param titleRes The string resource identifier used for the title.
* @return This ContextMenu so additional setters can be called.
*/
- public ContextMenu setHeaderTitle(int titleRes);
+ public ContextMenu setHeaderTitle(@StringRes int titleRes);
/**
* Sets the context menu header's title to the title given in <var>title</var>.
@@ -61,7 +63,7 @@
* @param iconRes The resource identifier used for the icon.
* @return This ContextMenu so additional setters can be called.
*/
- public ContextMenu setHeaderIcon(int iconRes);
+ public ContextMenu setHeaderIcon(@DrawableRes int iconRes);
/**
* Sets the context menu header's icon to the icon given in <var>icon</var>
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index cfb0297..71863b7 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -716,7 +716,7 @@
updateDisplayInfoLocked();
mDisplayInfo.getLogicalMetrics(outMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
- mDisplayAdjustments.getActivityToken());
+ mDisplayAdjustments.getConfiguration());
}
}
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index 35fb504..272740f 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -17,7 +17,7 @@
package android.view;
import android.content.res.CompatibilityInfo;
-import android.os.IBinder;
+import android.content.res.Configuration;
import java.util.Objects;
@@ -28,22 +28,18 @@
public static final DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS = new DisplayAdjustments();
private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
- private volatile IBinder mActivityToken;
+ private Configuration mConfiguration = Configuration.EMPTY;
public DisplayAdjustments() {
}
- public DisplayAdjustments(IBinder token) {
- mActivityToken = token;
+ public DisplayAdjustments(Configuration configuration) {
+ mConfiguration = configuration;
}
public DisplayAdjustments(DisplayAdjustments daj) {
- this (daj.getCompatibilityInfo(), daj.getActivityToken());
- }
-
- public DisplayAdjustments(CompatibilityInfo compatInfo, IBinder token) {
- setCompatibilityInfo(compatInfo);
- mActivityToken = token;
+ setCompatibilityInfo(daj.mCompatInfo);
+ mConfiguration = daj.mConfiguration;
}
public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
@@ -63,16 +59,16 @@
return mCompatInfo;
}
- public void setActivityToken(IBinder token) {
+ public void setConfiguration(Configuration configuration) {
if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
throw new IllegalArgumentException(
- "setActivityToken: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
+ "setConfiguration: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
}
- mActivityToken = token;
+ mConfiguration = configuration;
}
- public IBinder getActivityToken() {
- return mActivityToken;
+ public Configuration getConfiguration() {
+ return mConfiguration;
}
@Override
@@ -80,7 +76,7 @@
int hash = 17;
hash = hash * 31 + mCompatInfo.hashCode();
if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
- hash = hash * 31 + (mActivityToken == null ? 0 : mActivityToken.hashCode());
+ hash = hash * 31 + (mConfiguration == null ? 0 : mConfiguration.hashCode());
}
return hash;
}
@@ -92,6 +88,6 @@
}
DisplayAdjustments daj = (DisplayAdjustments)o;
return Objects.equals(daj.mCompatInfo, mCompatInfo) &&
- Objects.equals(daj.mActivityToken, mActivityToken);
+ Objects.equals(daj.mConfiguration, mConfiguration);
}
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 9feb681..ecf45b4 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -17,7 +17,7 @@
package android.view;
import android.content.res.CompatibilityInfo;
-import android.os.IBinder;
+import android.content.res.Configuration;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
@@ -401,16 +401,17 @@
public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
- displayAdjustments.getActivityToken(), appWidth, appHeight);
+ displayAdjustments.getConfiguration(), appWidth, appHeight);
}
- public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token) {
- getMetricsWithSize(outMetrics, ci, token, appWidth, appHeight);
+ public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
+ Configuration configuration) {
+ getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
}
public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
- IBinder token) {
- getMetricsWithSize(outMetrics, compatInfo, token, logicalWidth, logicalHeight);
+ Configuration configuration) {
+ getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
}
public int getNaturalWidth() {
@@ -431,17 +432,24 @@
}
private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
- IBinder token, int width, int height) {
+ Configuration configuration, int width, int height) {
outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
- outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
- outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
-
outMetrics.density = outMetrics.noncompatDensity =
logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
+ width = (configuration != null
+ && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
+ ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
+ height = (configuration != null
+ && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
+ ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
+
+ outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
+ outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
+
if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
compatInfo.applyToDisplayMetrics(outMetrics);
}
diff --git a/core/java/android/view/FrameInfo.java b/core/java/android/view/FrameInfo.java
new file mode 100644
index 0000000..c79547c
--- /dev/null
+++ b/core/java/android/view/FrameInfo.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class that contains all the timing information for the current frame. This
+ * is used in conjunction with the hardware renderer to provide
+ * continous-monitoring jank events
+ *
+ * All times in nanoseconds from CLOCK_MONOTONIC/System.nanoTime()
+ *
+ * To minimize overhead from System.nanoTime() calls we infer durations of
+ * things by knowing the ordering of the events. For example, to know how
+ * long layout & measure took it's displayListRecordStart - performTraversalsStart.
+ *
+ * These constants must be kept in sync with FrameInfo.h in libhwui and are
+ * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * to be quick to pass down to native via JNI, hence a pre-packed format
+ *
+ * @hide
+ */
+final class FrameInfo {
+
+ long[] mFrameInfo = new long[9];
+
+ // Various flags set to provide extra metadata about the current frame
+ private static final int FLAGS = 0;
+
+ // Is this the first-draw following a window layout?
+ public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
+
+ @IntDef(flag = true, value = {
+ FLAG_WINDOW_LAYOUT_CHANGED })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrameInfoFlags {}
+
+ // The intended vsync time, unadjusted by jitter
+ private static final int INTENDED_VSYNC = 1;
+
+ // Jitter-adjusted vsync time, this is what was used as input into the
+ // animation & drawing system
+ private static final int VSYNC = 2;
+
+ // The time of the oldest input event
+ private static final int OLDEST_INPUT_EVENT = 3;
+
+ // The time of the newest input event
+ private static final int NEWEST_INPUT_EVENT = 4;
+
+ // When input event handling started
+ private static final int HANDLE_INPUT_START = 5;
+
+ // When animation evaluations started
+ private static final int ANIMATION_START = 6;
+
+ // When ViewRootImpl#performTraversals() started
+ private static final int PERFORM_TRAVERSALS_START = 7;
+
+ // When View:draw() started
+ private static final int DRAW_START = 8;
+
+ public void setVsync(long intendedVsync, long usedVsync) {
+ mFrameInfo[INTENDED_VSYNC] = intendedVsync;
+ mFrameInfo[VSYNC] = usedVsync;
+ mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+ mFrameInfo[NEWEST_INPUT_EVENT] = 0;
+ mFrameInfo[FLAGS] = 0;
+ }
+
+ public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
+ if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
+ mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+ }
+ if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
+ mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+ }
+ }
+
+ public void markInputHandlingStart() {
+ mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+ }
+
+ public void markAnimationsStart() {
+ mFrameInfo[ANIMATION_START] = System.nanoTime();
+ }
+
+ public void markPerformTraversalsStart() {
+ mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+ }
+
+ public void markDrawStart() {
+ mFrameInfo[DRAW_START] = System.nanoTime();
+ }
+
+ public void addFlags(@FrameInfoFlags long flags) {
+ mFrameInfo[FLAGS] |= flags;
+ }
+
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c5c3f83..aa61885 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -278,7 +278,7 @@
/**
* Outputs extra debugging information in the specified file descriptor.
*/
- abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd);
+ abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args);
/**
* Loads system properties used by the renderer. This method is invoked
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 743f6b7..8ac8bc5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -91,6 +91,8 @@
IRemoteCallback startedCallback);
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight);
+ void overridePendingAppTransitionClipReveal(int startX, int startY,
+ int startWidth, int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp);
void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d08ab46..fc0148f 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -194,4 +194,19 @@
void onRectangleOnScreenRequested(IBinder token, in Rect rectangle);
IWindowId getWindowId(IBinder window);
+
+ /**
+ * When the system is dozing in a low-power partially suspended state, pokes a short
+ * lived wake lock and ensures that the display is ready to accept the next frame
+ * of content drawn in the window.
+ *
+ * This mechanism is bound to the window rather than to the display manager or the
+ * power manager so that the system can ensure that the window is actually visible
+ * and prevent runaway applications from draining the battery. This is similar to how
+ * FLAG_KEEP_SCREEN_ON works.
+ *
+ * This method is synchronous because it may need to acquire a wake lock before returning.
+ * The assumption is that this method will be called rather infrequently.
+ */
+ void pokeDrawLock(IBinder window);
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index a5225cb..1014573 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
@@ -369,7 +370,7 @@
* this is the root View; otherwise it is the root of the inflated
* XML file.
*/
- public View inflate(int resource, @Nullable ViewGroup root) {
+ public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
@@ -410,7 +411,7 @@
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
- public View inflate(int resource, @Nullable ViewGroup root, boolean attachToRoot) {
+ public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
diff --git a/core/java/android/view/Menu.java b/core/java/android/view/Menu.java
index 7157bc5..0c2e9cf 100644
--- a/core/java/android/view/Menu.java
+++ b/core/java/android/view/Menu.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.StringRes;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
@@ -148,7 +149,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added menu item.
*/
- public MenuItem add(int titleRes);
+ public MenuItem add(@StringRes int titleRes);
/**
* Add a new item to the menu. This item displays the given title for its
@@ -182,7 +183,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added menu item.
*/
- public MenuItem add(int groupId, int itemId, int order, int titleRes);
+ public MenuItem add(int groupId, int itemId, int order, @StringRes int titleRes);
/**
* Add a new sub-menu to the menu. This item displays the given title for
@@ -202,7 +203,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added sub-menu
*/
- SubMenu addSubMenu(final int titleRes);
+ SubMenu addSubMenu(@StringRes final int titleRes);
/**
* Add a new sub-menu to the menu. This item displays the given
@@ -239,7 +240,7 @@
* @param titleRes Resource identifier of title string.
* @return The newly added sub-menu
*/
- SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes);
+ SubMenu addSubMenu(int groupId, int itemId, int order, @StringRes int titleRes);
/**
* Add a group of menu items corresponding to actions that can be performed
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 5811c17..3492aa0 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -21,6 +21,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.MenuRes;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
@@ -101,7 +102,7 @@
* @param menu The Menu to inflate into. The items and submenus will be
* added to this Menu.
*/
- public void inflate(int menuRes, Menu menu) {
+ public void inflate(@MenuRes int menuRes, Menu menu) {
XmlResourceParser parser = null;
try {
parser = mContext.getResources().getLayout(menuRes);
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index e706c9c..9e8b97e 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -16,6 +16,9 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.LayoutRes;
+import android.annotation.StringRes;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -165,7 +168,7 @@
* @see #setTitleCondensed(CharSequence)
*/
- public MenuItem setTitle(int title);
+ public MenuItem setTitle(@StringRes int title);
/**
* Retrieve the current title of the item.
@@ -214,7 +217,7 @@
* @param iconRes The new icon (as a resource ID) to be displayed.
* @return This Item so additional setters can be called.
*/
- public MenuItem setIcon(int iconRes);
+ public MenuItem setIcon(@DrawableRes int iconRes);
/**
* Returns the icon for this item as a Drawable (getting it from resources if it hasn't been
@@ -511,7 +514,7 @@
*
* @see #setShowAsAction(int)
*/
- public MenuItem setActionView(int resId);
+ public MenuItem setActionView(@LayoutRes int resId);
/**
* Returns the currently set action view for this menu item.
diff --git a/core/java/android/view/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index 5f4d201..2a25fd2 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -25,7 +25,9 @@
import android.app.ActivityManagerNative;
import android.app.SearchManager;
import android.os.UserHandle;
+
import com.android.internal.R;
+import com.android.internal.view.ActionModeWrapper;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
@@ -2689,72 +2691,17 @@
if (mode != null) {
mActionMode = mode;
} else {
- if (mActionModeView == null) {
- if (isFloating()) {
- // Use the action bar theme.
- final TypedValue outValue = new TypedValue();
- final Theme baseTheme = mContext.getTheme();
- baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
-
- final Context actionBarContext;
- if (outValue.resourceId != 0) {
- final Theme actionBarTheme = mContext.getResources().newTheme();
- actionBarTheme.setTo(baseTheme);
- actionBarTheme.applyStyle(outValue.resourceId, true);
-
- actionBarContext = new ContextThemeWrapper(mContext, 0);
- actionBarContext.getTheme().setTo(actionBarTheme);
- } else {
- actionBarContext = mContext;
- }
-
- mActionModeView = new ActionBarContextView(actionBarContext);
- mActionModePopup = new PopupWindow(actionBarContext, null,
- R.attr.actionModePopupWindowStyle);
- mActionModePopup.setWindowLayoutType(
- WindowManager.LayoutParams.TYPE_APPLICATION);
- mActionModePopup.setContentView(mActionModeView);
- mActionModePopup.setWidth(MATCH_PARENT);
-
- actionBarContext.getTheme().resolveAttribute(
- R.attr.actionBarSize, outValue, true);
- final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
- actionBarContext.getResources().getDisplayMetrics());
- mActionModeView.setContentHeight(height);
- mActionModePopup.setHeight(WRAP_CONTENT);
- mShowActionModePopup = new Runnable() {
- public void run() {
- mActionModePopup.showAtLocation(
- mActionModeView.getApplicationWindowToken(),
- Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
- }
- };
- } else {
- ViewStub stub = (ViewStub) findViewById(
- R.id.action_mode_bar_stub);
- if (stub != null) {
- mActionModeView = (ActionBarContextView) stub.inflate();
- }
- }
- }
-
if (mActionModeView != null) {
mActionModeView.killMode();
- mode = new StandaloneActionMode(mActionModeView.getContext(), mActionModeView,
- wrappedCallback, mActionModePopup == null);
- if (callback.onCreateActionMode(mode, mode.getMenu())) {
- mode.invalidate();
- mActionModeView.initForMode(mode);
- mActionModeView.setVisibility(View.VISIBLE);
- mActionMode = mode;
- if (mActionModePopup != null) {
- post(mShowActionModePopup);
- }
- mActionModeView.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- } else {
- mActionMode = null;
- }
+ }
+ ActionModeWrapper wrapperMode = new ActionModeWrapper(
+ mContext, wrappedCallback, new StandaloneActionModeProvider());
+ if (callback.onCreateActionMode(wrapperMode, wrapperMode.getMenu())) {
+ mActionMode = wrapperMode;
+ wrapperMode.lockType();
+ mActionMode.invalidate();
+ } else {
+ mActionMode = null;
}
}
if (mActionMode != null && getCallback() != null && !isDestroyed()) {
@@ -2852,11 +2799,11 @@
// indicates that the window was either just added and received them for the
// first time, or the window size or position has changed.
boolean hasTopStableInset = insets.getStableInsetTop() != 0;
- disallowAnimate |= hasTopStableInset && !mLastHasTopStableInset;
+ disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
mLastHasTopStableInset = hasTopStableInset;
boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
- disallowAnimate |= hasBottomStableInset && !mLastHasBottomStableInset;
+ disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
mLastHasBottomStableInset = hasBottomStableInset;
}
@@ -3251,6 +3198,82 @@
}
/**
+ * Encapsulates the view creation for {@link StandaloneActionMode}.
+ */
+ private class StandaloneActionModeProvider
+ implements ActionModeWrapper.ActionModeProvider {
+
+ @Override
+ public ActionMode createActionMode(android.view.ActionMode.Callback callback,
+ MenuBuilder menuBuilder) {
+ if (mActionModeView == null) {
+ if (isFloating()) {
+ // Use the action bar theme.
+ final TypedValue outValue = new TypedValue();
+ final Theme baseTheme = mContext.getTheme();
+ baseTheme.resolveAttribute(R.attr.actionBarTheme, outValue, true);
+
+ final Context actionBarContext;
+ if (outValue.resourceId != 0) {
+ final Theme actionBarTheme = mContext.getResources().newTheme();
+ actionBarTheme.setTo(baseTheme);
+ actionBarTheme.applyStyle(outValue.resourceId, true);
+
+ actionBarContext = new ContextThemeWrapper(mContext, 0);
+ actionBarContext.getTheme().setTo(actionBarTheme);
+ } else {
+ actionBarContext = mContext;
+ }
+
+ mActionModeView = new ActionBarContextView(actionBarContext);
+ mActionModePopup = new PopupWindow(actionBarContext, null,
+ R.attr.actionModePopupWindowStyle);
+ mActionModePopup.setWindowLayoutType(
+ WindowManager.LayoutParams.TYPE_APPLICATION);
+ mActionModePopup.setContentView(mActionModeView);
+ mActionModePopup.setWidth(MATCH_PARENT);
+
+ actionBarContext.getTheme().resolveAttribute(
+ R.attr.actionBarSize, outValue, true);
+ final int height = TypedValue.complexToDimensionPixelSize(outValue.data,
+ actionBarContext.getResources().getDisplayMetrics());
+ mActionModeView.setContentHeight(height);
+ mActionModePopup.setHeight(WRAP_CONTENT);
+ mShowActionModePopup = new Runnable() {
+ public void run() {
+ mActionModePopup.showAtLocation(
+ mActionModeView.getApplicationWindowToken(),
+ Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
+ }
+ };
+ } else {
+ ViewStub stub = (ViewStub) findViewById(
+ R.id.action_mode_bar_stub);
+ if (stub != null) {
+ mActionModeView = (ActionBarContextView) stub.inflate();
+ }
+ }
+ }
+ if (mActionModeView != null) {
+ ActionMode mode = new StandaloneActionMode(
+ mActionModeView.getContext(), mActionModeView,
+ callback, mActionModePopup == null, menuBuilder);
+ mActionModeView.killMode();
+ mActionModeView.initForMode(mode);
+ mActionModeView.setVisibility(View.VISIBLE);
+ if (mActionModePopup != null) {
+ post(mShowActionModePopup);
+ }
+ mActionModeView.sendAccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ return mode;
+ }
+ return null;
+ }
+
+ }
+
+ /**
* Clears out internal reference when the action mode is destroyed.
*/
private class ActionModeCallbackWrapper implements ActionMode.Callback {
@@ -4148,12 +4171,6 @@
return mMediaController;
}
- private boolean isTranslucent() {
- TypedArray a = getWindowStyle();
- return a.getBoolean(a.getResourceId(
- R.styleable.Window_windowIsTranslucent, 0), false);
- }
-
@Override
public void setEnterTransition(Transition enterTransition) {
mEnterTransition = enterTransition;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 7dcad68..cf35ce5 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -18,6 +18,7 @@
import com.android.internal.util.XmlUtils;
+import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -192,7 +193,7 @@
* @throws Resources.NotFoundException if the resource was not found or the drawable
* linked in the resource was not found.
*/
- public static PointerIcon loadCustomIcon(Resources resources, int resourceId) {
+ public static PointerIcon loadCustomIcon(Resources resources, @XmlRes int resourceId) {
if (resources == null) {
throw new IllegalArgumentException("resources must not be null");
}
@@ -373,7 +374,7 @@
return true;
}
- private void loadResource(Context context, Resources resources, int resourceId) {
+ private void loadResource(Context context, Resources resources, @XmlRes int resourceId) {
final XmlResourceParser parser = resources.getXml(resourceId);
final int bitmapRes;
final float hotSpotX;
diff --git a/core/java/android/view/SubMenu.java b/core/java/android/view/SubMenu.java
index 196a183..38662b0 100644
--- a/core/java/android/view/SubMenu.java
+++ b/core/java/android/view/SubMenu.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.graphics.drawable.Drawable;
/**
@@ -38,7 +40,7 @@
* @param titleRes The string resource identifier used for the title.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setHeaderTitle(int titleRes);
+ public SubMenu setHeaderTitle(@StringRes int titleRes);
/**
* Sets the submenu header's title to the title given in <var>title</var>.
@@ -55,7 +57,7 @@
* @param iconRes The resource identifier used for the icon.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setHeaderIcon(int iconRes);
+ public SubMenu setHeaderIcon(@DrawableRes int iconRes);
/**
* Sets the submenu header's icon to the icon given in <var>icon</var>
@@ -88,7 +90,7 @@
* @param iconRes The new icon (as a resource ID) to be displayed.
* @return This SubMenu so additional setters can be called.
*/
- public SubMenu setIcon(int iconRes);
+ public SubMenu setIcon(@DrawableRes int iconRes);
/**
* Change the icon associated with this submenu's item in its parent menu.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index ad4a048..df0838f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,8 +16,7 @@
package android.view;
-import com.android.internal.R;
-
+import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -27,16 +26,18 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.util.LongSparseArray;
-import android.util.TimeUtils;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
+import com.android.internal.R;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashSet;
@@ -74,6 +75,14 @@
PROFILE_PROPERTY_VISUALIZE_BARS,
};
+ private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+ private static final int FLAG_DUMP_RESET = 1 << 1;
+
+ @IntDef(flag = true, value = {
+ FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DumpFlags {}
+
// Size of the rendered content.
private int mWidth, mHeight;
@@ -93,12 +102,12 @@
private final float mLightRadius;
private final int mAmbientShadowAlpha;
private final int mSpotShadowAlpha;
+ private final float mDensity;
private long mNativeProxy;
private boolean mInitialized = false;
private RenderNode mRootNode;
private Choreographer mChoreographer;
- private boolean mProfilingEnabled;
private boolean mRootNodeNeedsUpdate;
ThreadedRenderer(Context context, boolean translucent) {
@@ -110,6 +119,7 @@
(int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
a.recycle();
+ mDensity = context.getResources().getDisplayMetrics().density;
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
@@ -214,7 +224,7 @@
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight,
lightX, mLightY, mLightZ, mLightRadius,
- mAmbientShadowAlpha, mSpotShadowAlpha);
+ mAmbientShadowAlpha, mSpotShadowAlpha, mDensity);
}
@Override
@@ -233,32 +243,25 @@
}
@Override
- void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
+ void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
pw.flush();
- nDumpProfileInfo(mNativeProxy, fd);
- }
-
- private static int search(String[] values, String value) {
- for (int i = 0; i < values.length; i++) {
- if (values[i].equals(value)) return i;
+ int flags = 0;
+ for (int i = 0; i < args.length; i++) {
+ switch (args[i]) {
+ case "framestats":
+ flags |= FLAG_DUMP_FRAMESTATS;
+ break;
+ case "reset":
+ flags |= FLAG_DUMP_RESET;
+ break;
+ }
}
- return -1;
- }
-
- private static boolean checkIfProfilingRequested() {
- String profiling = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
- int graphType = search(VISUALIZERS, profiling);
- return (graphType >= 0) || Boolean.parseBoolean(profiling);
+ nDumpProfileInfo(mNativeProxy, fd, flags);
}
@Override
boolean loadSystemProperties() {
boolean changed = nLoadSystemProperties(mNativeProxy);
- boolean wantProfiling = checkIfProfilingRequested();
- if (wantProfiling != mProfilingEnabled) {
- mProfilingEnabled = wantProfiling;
- changed = true;
- }
if (changed) {
invalidateRoot();
}
@@ -307,20 +310,12 @@
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
attachInfo.mIgnoreDirtyState = true;
- long frameTimeNanos = mChoreographer.getFrameTimeNanos();
- attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
- long recordDuration = 0;
- if (mProfilingEnabled) {
- recordDuration = System.nanoTime();
- }
+ final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
+ choreographer.mFrameInfo.markDrawStart();
updateRootDisplayList(view, callbacks);
- if (mProfilingEnabled) {
- recordDuration = System.nanoTime() - recordDuration;
- }
-
attachInfo.mIgnoreDirtyState = false;
// register animating rendernodes which started animating prior to renderer
@@ -337,8 +332,8 @@
attachInfo.mPendingAnimatingRenderNodes = null;
}
- int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
- recordDuration, view.getResources().getDisplayMetrics().density);
+ final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
+ int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
@@ -500,10 +495,9 @@
private static native boolean nPauseSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height,
float lightX, float lightY, float lightZ, float lightRadius,
- int ambientShadowAlpha, int spotShadowAlpha);
+ int ambientShadowAlpha, int spotShadowAlpha, float density);
private static native void nSetOpaque(long nativeProxy, boolean opaque);
- private static native int nSyncAndDrawFrame(long nativeProxy,
- long frameTimeNanos, long recordDuration, float density);
+ private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
@@ -523,5 +517,6 @@
private static native void nStopDrawing(long nativeProxy);
private static native void nNotifyFramePending(long nativeProxy);
- private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
+ private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+ @DumpFlags int dumpFlags);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 04aafc1..502d5ee 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,8 +16,12 @@
package android.view;
+import android.animation.Animator;
import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
import android.animation.StateListAnimator;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,13 +34,10 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Insets;
-import android.graphics.Interpolator;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -1593,6 +1594,7 @@
* @see #setId(int)
* @see #getId()
*/
+ @IdRes
@ViewDebug.ExportedProperty(resolveId = true)
int mID = NO_ID;
@@ -4323,9 +4325,7 @@
* @hide This is the real method; the public one is shimmed to be safe to call from apps.
*/
protected void initializeFadingEdgeInternal(TypedArray a) {
- initScrollCache();
-
- mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
+ getScrollCache().fadingEdgeLength = a.getDimensionPixelSize(
R.styleable.View_fadingEdgeLength,
ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
}
@@ -4359,8 +4359,7 @@
* content in this view is visible.
*/
public void setFadingEdgeLength(int length) {
- initScrollCache();
- mScrollCache.fadingEdgeLength = length;
+ getScrollCache().fadingEdgeLength = length;
}
/**
@@ -4464,10 +4463,7 @@
* @hide
*/
protected void initializeScrollbarsInternal(TypedArray a) {
- initScrollCache();
-
- final ScrollabilityCache scrollabilityCache = mScrollCache;
-
+ final ScrollabilityCache scrollabilityCache = getScrollCache();
if (scrollabilityCache.scrollBar == null) {
scrollabilityCache.scrollBar = new ScrollBarDrawable();
scrollabilityCache.scrollBar.setCallback(this);
@@ -4475,23 +4471,16 @@
}
final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
-
- if (!fadeScrollbars) {
- scrollabilityCache.state = ScrollabilityCache.ON;
- }
- scrollabilityCache.fadeScrollBars = fadeScrollbars;
-
+ scrollabilityCache.setFadingEnabled(fadeScrollbars);
scrollabilityCache.scrollBarFadeDuration = a.getInt(
- R.styleable.View_scrollbarFadeDuration, ViewConfiguration
- .getScrollBarFadeDuration());
+ R.styleable.View_scrollbarFadeDuration,
+ ViewConfiguration.getScrollBarFadeDuration());
scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
R.styleable.View_scrollbarDefaultDelayBeforeFade,
ViewConfiguration.getScrollDefaultDelay());
-
-
scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
- com.android.internal.R.styleable.View_scrollbarSize,
+ R.styleable.View_scrollbarSize,
ViewConfiguration.get(mContext).getScaledScrollBarSize());
Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
@@ -4536,18 +4525,12 @@
}
/**
- * <p>
- * Initalizes the scrollability cache if necessary.
- * </p>
+ * Returns the scrollability cache, initializing a new cache if necessary.
*/
- private void initScrollCache() {
- if (mScrollCache == null) {
- mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
- }
- }
-
private ScrollabilityCache getScrollCache() {
- initScrollCache();
+ if (mScrollCache == null) {
+ mScrollCache = new ScrollabilityCache(this);
+ }
return mScrollCache;
}
@@ -6062,7 +6045,7 @@
* @param id The labeled view id.
*/
@RemotableViewMethod
- public void setLabelFor(int id) {
+ public void setLabelFor(@IdRes int id) {
if (mLabelForId == id) {
return;
}
@@ -11568,31 +11551,30 @@
* @see #setVerticalScrollBarEnabled(boolean)
*/
protected boolean awakenScrollBars() {
- return mScrollCache != null &&
- awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
+ return mScrollCache != null
+ && awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
}
/**
* Trigger the scrollbars to draw.
+ * <p>
* This method differs from awakenScrollBars() only in its default duration.
* initialAwakenScrollBars() will show the scroll bars for longer than
* usual to give the user more of a chance to notice them.
*
* @return true if the animation is played, false otherwise.
+ * @see #awakenScrollBars()
*/
private boolean initialAwakenScrollBars() {
- return mScrollCache != null &&
- awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
+ return mScrollCache != null
+ && awakenScrollBars(mScrollCache.scrollBarDelayBeforeInitialFade, true);
}
/**
- * <p>
* Trigger the scrollbars to draw. When invoked this method starts an
* animation to fade the scrollbars out after a fixed delay. If a subclass
* provides animated scrolling, the start delay should equal the duration of
* the scrolling animation.
- * </p>
- *
* <p>
* The animation starts only if at least one of the scrollbars is enabled,
* as specified by {@link #isHorizontalScrollBarEnabled()} and
@@ -11600,18 +11582,14 @@
* this method returns true, and false otherwise. If the animation is
* started, this method calls {@link #invalidate()}; in that case the caller
* should not call {@link #invalidate()}.
- * </p>
- *
* <p>
* This method should be invoked every time a subclass directly updates the
* scroll parameters.
- * </p>
*
- * @param startDelay the delay, in milliseconds, after which the animation
- * should start; when the delay is 0, the animation starts
- * immediately
+ * @param fadeOutDelay the delay in milliseconds before the fade out
+ * animation should start, or 0 to start the animation
+ * immediately
* @return true if the animation is played, false otherwise
- *
* @see #scrollBy(int, int)
* @see #scrollTo(int, int)
* @see #isHorizontalScrollBarEnabled()
@@ -11619,18 +11597,15 @@
* @see #setHorizontalScrollBarEnabled(boolean)
* @see #setVerticalScrollBarEnabled(boolean)
*/
- protected boolean awakenScrollBars(int startDelay) {
- return awakenScrollBars(startDelay, true);
+ protected boolean awakenScrollBars(int fadeOutDelay) {
+ return awakenScrollBars(fadeOutDelay, true);
}
/**
- * <p>
* Trigger the scrollbars to draw. When invoked this method starts an
* animation to fade the scrollbars out after a fixed delay. If a subclass
* provides animated scrolling, the start delay should equal the duration of
* the scrolling animation.
- * </p>
- *
* <p>
* The animation starts only if at least one of the scrollbars is enabled,
* as specified by {@link #isHorizontalScrollBarEnabled()} and
@@ -11639,21 +11614,18 @@
* started, this method calls {@link #invalidate()} if the invalidate parameter
* is set to true; in that case the caller
* should not call {@link #invalidate()}.
- * </p>
- *
* <p>
* This method should be invoked every time a subclass directly updates the
* scroll parameters.
- * </p>
+ * <p>
+ * <strong>Note:</strong> If the view has not explicitly requested
+ * scrollbars prior calling this method, this is a no-op.
*
- * @param startDelay the delay, in milliseconds, after which the animation
- * should start; when the delay is 0, the animation starts
- * immediately
- *
- * @param invalidate Whether this method should call invalidate
- *
+ * @param fadeOutDelay the delay in milliseconds before the fade out
+ * animation should start, or 0 to start the animation
+ * immediately
+ * @param invalidate whether this method should call invalidate
* @return true if the animation is played, false otherwise
- *
* @see #scrollBy(int, int)
* @see #scrollTo(int, int)
* @see #isHorizontalScrollBarEnabled()
@@ -11661,50 +11633,15 @@
* @see #setHorizontalScrollBarEnabled(boolean)
* @see #setVerticalScrollBarEnabled(boolean)
*/
- protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
- final ScrollabilityCache scrollCache = mScrollCache;
-
- if (scrollCache == null || !scrollCache.fadeScrollBars) {
+ protected boolean awakenScrollBars(int fadeOutDelay, boolean invalidate) {
+ if (mScrollCache == null
+ || (!isHorizontalScrollBarEnabled() && !isVerticalScrollBarEnabled())) {
+ // We're not supposed to show scroll bars right now.
return false;
}
- if (scrollCache.scrollBar == null) {
- scrollCache.scrollBar = new ScrollBarDrawable();
- scrollCache.scrollBar.setCallback(this);
- scrollCache.scrollBar.setState(getDrawableState());
- }
-
- if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
-
- if (invalidate) {
- // Invalidate to show the scrollbars
- postInvalidateOnAnimation();
- }
-
- if (scrollCache.state == ScrollabilityCache.OFF) {
- // FIXME: this is copied from WindowManagerService.
- // We should get this value from the system when it
- // is possible to do so.
- final int KEY_REPEAT_FIRST_DELAY = 750;
- startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
- }
-
- // Tell mScrollCache when we should start fading. This may
- // extend the fade start time if one was already scheduled
- long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
- scrollCache.fadeStartTime = fadeStartTime;
- scrollCache.state = ScrollabilityCache.ON;
-
- // Schedule our fader to run, unscheduling any old ones first
- if (mAttachInfo != null) {
- mAttachInfo.mHandler.removeCallbacks(scrollCache);
- mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
- }
-
- return true;
- }
-
- return false;
+ mScrollCache.awakenScrollBars(fadeOutDelay);
+ return true;
}
/**
@@ -12385,7 +12322,7 @@
public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
if (horizontalFadingEdgeEnabled) {
- initScrollCache();
+ getScrollCache();
}
mViewFlags ^= FADING_EDGE_HORIZONTAL;
@@ -12422,7 +12359,7 @@
public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
if (verticalFadingEdgeEnabled) {
- initScrollCache();
+ getScrollCache();
}
mViewFlags ^= FADING_EDGE_VERTICAL;
@@ -12562,14 +12499,7 @@
* @attr ref android.R.styleable#View_fadeScrollbars
*/
public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
- initScrollCache();
- final ScrollabilityCache scrollabilityCache = mScrollCache;
- scrollabilityCache.fadeScrollBars = fadeScrollbars;
- if (fadeScrollbars) {
- scrollabilityCache.state = ScrollabilityCache.OFF;
- } else {
- scrollabilityCache.state = ScrollabilityCache.ON;
- }
+ getScrollCache().setFadingEnabled(fadeScrollbars);
}
/**
@@ -12581,7 +12511,7 @@
* @attr ref android.R.styleable#View_fadeScrollbars
*/
public boolean isScrollbarFadingEnabled() {
- return mScrollCache != null && mScrollCache.fadeScrollBars;
+ return mScrollCache != null && mScrollCache.isFadingEnabled();
}
/**
@@ -12863,129 +12793,85 @@
}
/**
- * <p>Request the drawing of the horizontal and the vertical scrollbar. The
- * scrollbars are painted only if they have been awakened first.</p>
+ * Request the drawing of the horizontal and the vertical scrollbar. The
+ * scrollbars are painted only if they have been awakened first.
*
* @param canvas the canvas on which to draw the scrollbars
- *
* @see #awakenScrollBars(int)
*/
protected final void onDrawScrollBars(Canvas canvas) {
- // scrollbars are drawn only when the animation is running
final ScrollabilityCache cache = mScrollCache;
- if (cache != null) {
+ if (cache == null) {
+ // This view does not currently support scrolling.
+ return;
+ }
- int state = cache.state;
+ final int viewFlags = mViewFlags;
+ final boolean drawHorizontalScrollBar =
+ (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
+ final boolean drawVerticalScrollBar =
+ (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
+ && !isVerticalScrollBarHidden();
+ if (!drawVerticalScrollBar && !drawHorizontalScrollBar) {
+ // This view does not currently draw scrollbars.
+ return;
+ }
- if (state == ScrollabilityCache.OFF) {
- return;
+ final ScrollBarDrawable scrollBar = cache.scrollBar;
+ final int width = mRight - mLeft;
+ final int height = mBottom - mTop;
+ final int scrollX = mScrollX;
+ final int scrollY = mScrollY;
+ final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
+
+ if (drawHorizontalScrollBar) {
+ int size = scrollBar.getSize(false);
+ if (size <= 0) {
+ size = cache.scrollBarSize;
}
- boolean invalidate = false;
+ scrollBar.setParameters(computeHorizontalScrollRange(), computeHorizontalScrollOffset(),
+ computeHorizontalScrollExtent(), false);
+ final int verticalScrollBarGap = drawVerticalScrollBar ?
+ getVerticalScrollbarWidth() : 0;
- if (state == ScrollabilityCache.FADING) {
- // We're fading -- get our fade interpolation
- if (cache.interpolatorValues == null) {
- cache.interpolatorValues = new float[1];
- }
+ final int left = scrollX + (mPaddingLeft & inside);
+ final int right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
+ final int top = scrollY + height - size - (mUserPaddingBottom & inside);
+ final int bottom = top + size;
- float[] values = cache.interpolatorValues;
+ onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
+ }
- // Stops the animation if we're done
- if (cache.scrollBarInterpolator.timeToValues(values) ==
- Interpolator.Result.FREEZE_END) {
- cache.state = ScrollabilityCache.OFF;
- } else {
- cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
- }
+ if (drawVerticalScrollBar) {
+ int size = scrollBar.getSize(true);
+ if (size <= 0) {
+ size = cache.scrollBarSize;
+ }
- // This will make the scroll bars inval themselves after
- // drawing. We only want this when we're fading so that
- // we prevent excessive redraws
- invalidate = true;
+ scrollBar.setParameters(computeVerticalScrollRange(), computeVerticalScrollOffset(),
+ computeVerticalScrollExtent(), true);
+
+ final int verticalScrollbarPosition;
+ if (mVerticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
+ verticalScrollbarPosition = isLayoutRtl() ?
+ SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
} else {
- // We're just on -- but we may have been fading before so
- // reset alpha
- cache.scrollBar.mutate().setAlpha(255);
+ verticalScrollbarPosition = mVerticalScrollbarPosition;
}
-
- final int viewFlags = mViewFlags;
-
- final boolean drawHorizontalScrollBar =
- (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
- final boolean drawVerticalScrollBar =
- (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
- && !isVerticalScrollBarHidden();
-
- if (drawVerticalScrollBar || drawHorizontalScrollBar) {
- final int width = mRight - mLeft;
- final int height = mBottom - mTop;
-
- final ScrollBarDrawable scrollBar = cache.scrollBar;
-
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
- final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
-
- int left;
- int top;
- int right;
- int bottom;
-
- if (drawHorizontalScrollBar) {
- int size = scrollBar.getSize(false);
- if (size <= 0) {
- size = cache.scrollBarSize;
- }
-
- scrollBar.setParameters(computeHorizontalScrollRange(),
- computeHorizontalScrollOffset(),
- computeHorizontalScrollExtent(), false);
- final int verticalScrollBarGap = drawVerticalScrollBar ?
- getVerticalScrollbarWidth() : 0;
- top = scrollY + height - size - (mUserPaddingBottom & inside);
- left = scrollX + (mPaddingLeft & inside);
- right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
- bottom = top + size;
- onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
- if (invalidate) {
- invalidate(left, top, right, bottom);
- }
- }
-
- if (drawVerticalScrollBar) {
- int size = scrollBar.getSize(true);
- if (size <= 0) {
- size = cache.scrollBarSize;
- }
-
- scrollBar.setParameters(computeVerticalScrollRange(),
- computeVerticalScrollOffset(),
- computeVerticalScrollExtent(), true);
- int verticalScrollbarPosition = mVerticalScrollbarPosition;
- if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
- verticalScrollbarPosition = isLayoutRtl() ?
- SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
- }
- switch (verticalScrollbarPosition) {
- default:
- case SCROLLBAR_POSITION_RIGHT:
- left = scrollX + width - size - (mUserPaddingRight & inside);
- break;
- case SCROLLBAR_POSITION_LEFT:
- left = scrollX + (mUserPaddingLeft & inside);
- break;
- }
- top = scrollY + (mPaddingTop & inside);
- right = left + size;
- bottom = scrollY + height - (mUserPaddingBottom & inside);
- onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
- if (invalidate) {
- invalidate(left, top, right, bottom);
- }
- }
+ final int left;
+ if (verticalScrollbarPosition == SCROLLBAR_POSITION_LEFT) {
+ left = scrollX + (mUserPaddingLeft & inside);
+ } else {
+ left = scrollX + width - size - (mUserPaddingRight & inside);
}
+
+ final int top = scrollY + (mPaddingTop & inside);
+ final int right = left + size;
+ final int bottom = scrollY + height - (mUserPaddingBottom & inside);
+
+ onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
}
}
@@ -15349,7 +15235,7 @@
canvas.saveLayer(right - length, top, right, bottom, null, flags);
}
} else {
- scrollabilityCache.setFadeColor(solidColor);
+ scrollabilityCache.setFadingEdgeColor(solidColor);
}
// Step 3, draw the content
@@ -15359,9 +15245,9 @@
dispatchDraw(canvas);
// Step 5, draw the fade effect and restore layers
- final Paint p = scrollabilityCache.paint;
+ final Paint p = scrollabilityCache.fadingEdgePaint;
final Matrix matrix = scrollabilityCache.matrix;
- final Shader fade = scrollabilityCache.shader;
+ final Shader fade = scrollabilityCache.fadingEdgeShader;
if (drawTop) {
matrix.setScale(1, fadeHeight * topFadeStrength);
@@ -16242,7 +16128,7 @@
* @attr ref android.R.styleable#View_background
*/
@RemotableViewMethod
- public void setBackgroundResource(int resid) {
+ public void setBackgroundResource(@DrawableRes int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}
@@ -17070,7 +16956,7 @@
* @param id the id of the view to be found
* @return the view of the specified id, null if cannot be found
*/
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
return this;
}
@@ -17109,7 +16995,8 @@
* @param id The id to search for.
* @return The view that has the given id in the hierarchy or null
*/
- public final View findViewById(int id) {
+ @Nullable
+ public final View findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
@@ -17224,7 +17111,7 @@
*
* @attr ref android.R.styleable#View_id
*/
- public void setId(int id) {
+ public void setId(@IdRes int id) {
mID = id;
if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
mID = generateViewId();
@@ -17264,6 +17151,7 @@
* @see #findViewById(int)
* @attr ref android.R.styleable#View_id
*/
+ @IdRes
@ViewDebug.CapturedViewProperty
public int getId() {
return mID;
@@ -20619,121 +20507,164 @@
}
/**
- * <p>ScrollabilityCache holds various fields used by a View when scrolling
+ * ScrollabilityCache holds various fields used by a View when scrolling
* is supported. This avoids keeping too many unused fields in most
- * instances of View.</p>
+ * instances of View.
*/
- private static class ScrollabilityCache implements Runnable {
+ private static class ScrollabilityCache {
+ public final Paint fadingEdgePaint = new Paint();
+ public final Matrix matrix = new Matrix();
+
+ /** The view that owns this cache. */
+ private final View mHost;
/**
- * Scrollbars are not visible
+ * Minimum delay in milliseconds before the fade-out animation begins.
+ * Only used if the scrollbar was previously invisible.
*/
- public static final int OFF = 0;
+ private static final int MIN_FADE_DELAY_FROM_OFF = 750;
/**
- * Scrollbars are visible
+ * Default delay in milliseconds before the fade-out animation begins.
*/
- public static final int ON = 1;
-
- /**
- * Scrollbars are fading away
- */
- public static final int FADING = 2;
-
- public boolean fadeScrollBars;
-
- public int fadingEdgeLength;
public int scrollBarDefaultDelayBeforeFade;
+
+ /**
+ * Delay in milliseconds before the fade-out animation begins. Only
+ * used if the scrollbar is being shown to the user for the first time.
+ */
+ public int scrollBarDelayBeforeInitialFade;
+
+ /** Duration in milliseconds of the fade-out animation. */
public int scrollBarFadeDuration;
- public int scrollBarSize;
public ScrollBarDrawable scrollBar;
- public float[] interpolatorValues;
- public View host;
-
- public final Paint paint;
- public final Matrix matrix;
- public Shader shader;
-
- public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
-
- private static final float[] OPAQUE = { 255 };
- private static final float[] TRANSPARENT = { 0.0f };
+ public Shader fadingEdgeShader;
+ public int fadingEdgeLength;
+ public int scrollBarSize;
/**
- * When fading should start. This time moves into the future every time
- * a new scroll happens. Measured based on SystemClock.uptimeMillis()
+ * Whether scrollbar fading is enabled. If false, scrollbars are always
+ * visible.
*/
- public long fadeStartTime;
+ private boolean mIsFadingEnabled;
+ private Animator mFadeAnim;
+ private int mFadingEdgeLastColor;
- /**
- * The current state of the scrollbars: ON, OFF, or FADING
- */
- public int state = OFF;
+ public ScrollabilityCache(View host) {
+ mHost = host;
- private int mLastColor;
-
- public ScrollabilityCache(ViewConfiguration configuration, View host) {
- fadingEdgeLength = configuration.getScaledFadingEdgeLength();
- scrollBarSize = configuration.getScaledScrollBarSize();
- scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
+ scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
+ scrollBarDelayBeforeInitialFade = ViewConfiguration.getScrollDefaultInitialDelay();
- paint = new Paint();
- matrix = new Matrix();
- // use use a height of 1, and then wack the matrix each time we
- // actually use it.
- shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
- paint.setShader(shader);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ final ViewConfiguration configuration = ViewConfiguration.get(host.getContext());
+ scrollBarSize = configuration.getScaledScrollBarSize();
+ fadingEdgeLength = configuration.getScaledFadingEdgeLength();
- this.host = host;
+ // Force the fading edge color to change.
+ mFadingEdgeLastColor = -1;
+ setFadingEdgeColor(0);
}
- public void setFadeColor(int color) {
- if (color != mLastColor) {
- mLastColor = color;
+ public void setFadingEdgeColor(int color) {
+ if (mFadingEdgeLastColor != color) {
+ mFadingEdgeLastColor = color;
+ final int color0;
+ final int color1;
+ final PorterDuffXfermode xfermode;
if (color != 0) {
- shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
- color & 0x00FFFFFF, Shader.TileMode.CLAMP);
- paint.setShader(shader);
- // Restore the default transfer mode (src_over)
- paint.setXfermode(null);
+ color0 = color | 0xFF000000;
+ color1 = color & 0x00FFFFFF;
+ xfermode = null;
} else {
- shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
- paint.setShader(shader);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ color0 = 0xFF000000;
+ color1 = 0;
+ xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
}
+
+ // Use a height of 1 and then whack the matrix each time we
+ // actually use it.
+ fadingEdgeShader = new LinearGradient(
+ 0, 0, 0, 1, color0, color1, Shader.TileMode.CLAMP);
+ fadingEdgePaint.setShader(fadingEdgeShader);
+ fadingEdgePaint.setXfermode(xfermode);
}
}
- public void run() {
- long now = AnimationUtils.currentAnimationTimeMillis();
- if (now >= fadeStartTime) {
+ public void setFadingEnabled(boolean enabled) {
+ if (mIsFadingEnabled != enabled) {
+ mIsFadingEnabled = enabled;
- // the animation fades the scrollbars out by changing
- // the opacity (alpha) from fully opaque to fully
- // transparent
- int nextFrame = (int) now;
- int framesCount = 0;
-
- Interpolator interpolator = scrollBarInterpolator;
-
- // Start opaque
- interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
-
- // End transparent
- nextFrame += scrollBarFadeDuration;
- interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
-
- state = FADING;
-
- // Kick off the fade animation
- host.invalidate(true);
+ setFadingAlpha(enabled ? 0 : 255);
}
}
+
+ public boolean isFadingEnabled() {
+ return mIsFadingEnabled;
+ }
+
+ /**
+ * Cancels any ongoing or pending fade animations and immediately sets
+ * the scroll bar alpha value.
+ *
+ * @param alpha the scrollbar alpha value
+ */
+ public void setFadingAlpha(int alpha) {
+ if (mFadeAnim != null) {
+ mFadeAnim.cancel();
+ mFadeAnim = null;
+ }
+ mHost.removeCallbacks(mFadeOutRunnable);
+
+ scrollBar.setAlpha(alpha);
+ }
+
+ /**
+ * If fading is enabled, cancels any ongoing or pending fade animations
+ * and immediately sets the scroll bar alpha value to the maximum, then
+ * posts a delayed fade-out animation.
+ *
+ * @param fadeOutDelay the delay before the fade-out animation starts
+ * @return {@code true} if the scroll bars changed, false otherwise
+ */
+ public boolean awakenScrollBars(int fadeOutDelay) {
+ if (!mIsFadingEnabled) {
+ return false;
+ }
+
+ if (scrollBar == null) {
+ scrollBar = new ScrollBarDrawable();
+ scrollBar.setCallback(mHost);
+ scrollBar.setState(mHost.getDrawableState());
+ }
+
+ // Removes pending callbacks.
+ setFadingAlpha(255);
+
+ final int startingAlpha = scrollBar.getAlpha();
+ if (startingAlpha == 0) {
+ fadeOutDelay = Math.max(ScrollabilityCache.MIN_FADE_DELAY_FROM_OFF, fadeOutDelay);
+ }
+
+ mHost.postDelayed(mFadeOutRunnable, fadeOutDelay);
+
+ return true;
+ }
+
+ private final Runnable mFadeOutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ final ObjectAnimator anim = ObjectAnimator.ofInt(
+ scrollBar, ScrollBarDrawable.ALPHA, 0);
+ anim.setDuration(scrollBarFadeDuration);
+ anim.start();
+
+ mFadeAnim = anim;
+ }
+ };
}
/**
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 4e91ad4..d733513 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -47,6 +47,12 @@
private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
/**
+ * Default delay before the scrollbars fade in milliseconds for the first
+ * time they are shown to the user.
+ */
+ private static final int SCROLL_BAR_DEFAULT_INITIAL_DELAY = 1500;
+
+ /**
* Defines the length of the fading edges in dips
*/
private static final int FADING_EDGE_LENGTH = 12;
@@ -395,13 +401,23 @@
}
/**
- * @return Default delay before the scrollbars fade in milliseconds
+ * @return Default delay in milliseconds before the scrollbars fade out
+ * after they have been awoken.
*/
public static int getScrollDefaultDelay() {
return SCROLL_BAR_DEFAULT_DELAY;
}
/**
+ * @return Default delay in milliseconds before the scrollbars fade out
+ * after they are initially shown to the user.
+ * @hide Pending cleanup of ViewConfiguration values.
+ */
+ public static int getScrollDefaultInitialDelay() {
+ return SCROLL_BAR_DEFAULT_INITIAL_DELAY;
+ }
+
+ /**
* @return the length of the fading edges in dips
*
* @deprecated Use {@link #getScaledFadingEdgeLength()} instead.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e1cee1e..a49d8c3 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -17,6 +17,7 @@
package android.view;
import android.animation.LayoutTransition;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
@@ -1208,7 +1209,7 @@
* {@inheritDoc}
*/
public void bringChildToFront(View child) {
- int index = indexOfChild(child);
+ final int index = indexOfChild(child);
if (index >= 0) {
removeFromArray(index);
addInArray(child, mChildrenCount);
@@ -3612,7 +3613,7 @@
* {@hide}
*/
@Override
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
if (id == mID) {
return this;
}
@@ -3771,7 +3772,7 @@
* {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
*
* @param child the child view to add
- * @param index the position at which to add the child
+ * @param index the position at which to add the child or -1 to add last
* @param params the layout parameters to set on the child
*/
public void addView(View child, int index, LayoutParams params) {
@@ -3887,7 +3888,7 @@
* If index is negative, it means put it at the end of the list.
*
* @param child the view to add to the group
- * @param index the index at which the child must be added
+ * @param index the index at which the child must be added or -1 to add last
* @param params the layout parameters to associate with the child
* @return true if the child was added, false otherwise
*/
@@ -3902,7 +3903,7 @@
* If index is negative, it means put it at the end of the list.
*
* @param child the view to add to the group
- * @param index the index at which the child must be added
+ * @param index the index at which the child must be added or -1 to add last
* @param params the layout parameters to associate with the child
* @param preventRequestLayout if true, calling this method will not trigger a
* layout request on child
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fb2a8d8..a5fa5ed 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -47,6 +47,7 @@
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.SystemClock;
@@ -56,6 +57,7 @@
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
@@ -478,7 +480,6 @@
CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator();
- mDisplayAdjustments.setActivityToken(attrs.token);
// If the application owns the surface, don't enable hardware acceleration
if (mSurfaceHolder == null) {
@@ -838,6 +839,7 @@
final int newDisplayState = mDisplay.getState();
if (oldDisplayState != newDisplayState) {
mAttachInfo.mDisplayState = newDisplayState;
+ pokeDrawLockIfNeeded();
if (oldDisplayState != Display.STATE_UNKNOWN) {
final int oldScreenState = toViewScreenState(oldDisplayState);
final int newScreenState = toViewScreenState(newDisplayState);
@@ -868,6 +870,19 @@
}
};
+ void pokeDrawLockIfNeeded() {
+ final int displayState = mAttachInfo.mDisplayState;
+ if (mView != null && mAdded && mTraversalScheduled
+ && (displayState == Display.STATE_DOZE
+ || displayState == Display.STATE_DOZE_SUSPEND)) {
+ try {
+ mWindowSession.pokeDrawLock(mWindow);
+ } catch (RemoteException ex) {
+ // System server died, oh well.
+ }
+ }
+ }
+
@Override
public void requestFitSystemWindows() {
checkThread();
@@ -1042,6 +1057,7 @@
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
+ pokeDrawLockIfNeeded();
}
}
@@ -1343,7 +1359,7 @@
boolean insetsChanged = false;
- boolean layoutRequested = mLayoutRequested && !mStopped;
+ boolean layoutRequested = mLayoutRequested && (!mStopped || mReportNextDraw);
if (layoutRequested) {
final Resources res = mView.getContext().getResources();
@@ -1514,6 +1530,7 @@
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
}
+ mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
}
final int surfaceGenerationId = mSurface.getGenerationId();
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
@@ -1775,7 +1792,7 @@
}
}
- if (!mStopped) {
+ if (!mStopped || mReportNextDraw) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
@@ -1848,7 +1865,7 @@
}
}
- final boolean didLayout = layoutRequested && !mStopped;
+ final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
@@ -2517,6 +2534,9 @@
}
}
+ mAttachInfo.mDrawingTime =
+ mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
+
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
// If accessibility focus moved, always invalidate the root.
@@ -2636,7 +2656,6 @@
dirty.setEmpty();
mIsAnimating = false;
- attachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.PFLAG_DRAWN;
if (DEBUG_DRAW) {
@@ -3081,17 +3100,6 @@
return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
}
- private static void forceLayout(View view) {
- view.forceLayout();
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- final int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- forceLayout(group.getChildAt(i));
- }
- }
- }
-
private final static int MSG_INVALIDATE = 1;
private final static int MSG_INVALIDATE_RECT = 2;
private final static int MSG_DIE = 3;
@@ -3225,10 +3233,6 @@
mReportNextDraw = true;
}
- if (mView != null) {
- forceLayout(mView);
- }
-
requestLayout();
}
break;
@@ -3243,9 +3247,6 @@
mWinFrame.top = t;
mWinFrame.bottom = t + h;
- if (mView != null) {
- forceLayout(mView);
- }
requestLayout();
}
break;
@@ -5790,6 +5791,16 @@
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
+ long eventTime = q.mEvent.getEventTimeNano();
+ long oldestEventTime = eventTime;
+ if (q.mEvent instanceof MotionEvent) {
+ MotionEvent me = (MotionEvent)q.mEvent;
+ if (me.getHistorySize() > 0) {
+ oldestEventTime = me.getHistoricalEventTimeNano(0);
+ }
+ }
+ mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
+
deliverInputEvent(q);
}
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index 9f9ed5b..ec852e8 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -16,6 +16,8 @@
package android.view;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -87,7 +89,7 @@
* @param context The application's environment.
* @param layoutResource The reference to a layout resource that will be inflated.
*/
- public ViewStub(Context context, int layoutResource) {
+ public ViewStub(Context context, @LayoutRes int layoutResource) {
this(context, null);
mLayoutResource = layoutResource;
@@ -125,6 +127,7 @@
* @see #setInflatedId(int)
* @attr ref android.R.styleable#ViewStub_inflatedId
*/
+ @IdRes
public int getInflatedId() {
return mInflatedId;
}
@@ -140,7 +143,7 @@
* @attr ref android.R.styleable#ViewStub_inflatedId
*/
@android.view.RemotableViewMethod
- public void setInflatedId(int inflatedId) {
+ public void setInflatedId(@IdRes int inflatedId) {
mInflatedId = inflatedId;
}
@@ -156,6 +159,7 @@
* @see #inflate()
* @attr ref android.R.styleable#ViewStub_layout
*/
+ @LayoutRes
public int getLayoutResource() {
return mLayoutResource;
}
@@ -173,7 +177,7 @@
* @attr ref android.R.styleable#ViewStub_layout
*/
@android.view.RemotableViewMethod
- public void setLayoutResource(int layoutResource) {
+ public void setLayoutResource(@LayoutRes int layoutResource) {
mLayoutResource = layoutResource;
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1456b52..e332135 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -16,6 +16,9 @@
package android.view;
+import android.annotation.DrawableRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -984,7 +987,8 @@
*
* @return The view if found or null otherwise.
*/
- public View findViewById(int id) {
+ @Nullable
+ public View findViewById(@IdRes int id) {
return getDecorView().findViewById(id);
}
@@ -997,7 +1001,7 @@
* @param layoutResID Resource ID to be inflated.
* @see #setContentView(View, android.view.ViewGroup.LayoutParams)
*/
- public abstract void setContentView(int layoutResID);
+ public abstract void setContentView(@LayoutRes int layoutResID);
/**
* Convenience for
@@ -1127,7 +1131,7 @@
* @param resId The resource identifier of a drawable resource which will
* be installed as the new background.
*/
- public void setBackgroundDrawableResource(int resId) {
+ public void setBackgroundDrawableResource(@DrawableRes int resId) {
setBackgroundDrawable(mContext.getDrawable(resId));
}
@@ -1143,7 +1147,7 @@
/**
* Set the value for a drawable feature of this window, from a resource
- * identifier. You must have called requestFeauture(featureId) before
+ * identifier. You must have called requestFeature(featureId) before
* calling this function.
*
* @see android.content.res.Resources#getDrawable(int)
@@ -1152,7 +1156,7 @@
* constant by Window.
* @param resId Resource identifier of the desired image.
*/
- public abstract void setFeatureDrawableResource(int featureId, int resId);
+ public abstract void setFeatureDrawableResource(int featureId, @DrawableRes int resId);
/**
* Set the value for a drawable feature of this window, from a URI. You
@@ -1422,7 +1426,7 @@
*
* @param resId resource ID of a drawable to set
*/
- public void setIcon(int resId) { }
+ public void setIcon(@DrawableRes int resId) { }
/**
* Set the default icon for this window.
@@ -1431,7 +1435,7 @@
*
* @hide
*/
- public void setDefaultIcon(int resId) { }
+ public void setDefaultIcon(@DrawableRes int resId) { }
/**
* Set the logo for this window. A logo is often shown in place of an
@@ -1440,7 +1444,7 @@
*
* @param resId resource ID of a drawable to set
*/
- public void setLogo(int resId) { }
+ public void setLogo(@DrawableRes int resId) { }
/**
* Set the default logo for this window.
@@ -1449,7 +1453,7 @@
*
* @hide
*/
- public void setDefaultLogo(int resId) { }
+ public void setDefaultLogo(@DrawableRes int resId) { }
/**
* Set focus locally. The window should have the
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 279627a..1cebe3f 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -492,7 +492,7 @@
}
}
- public void dumpGfxInfo(FileDescriptor fd) {
+ public void dumpGfxInfo(FileDescriptor fd, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new FastPrintWriter(fout);
try {
@@ -509,7 +509,7 @@
HardwareRenderer renderer =
root.getView().mAttachInfo.mHardwareRenderer;
if (renderer != null) {
- renderer.dumpGfxInfo(pw, fd);
+ renderer.dumpGfxInfo(pw, fd, args);
}
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index f557b97..7b4640b 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -20,7 +20,7 @@
import android.graphics.Region;
import android.hardware.display.DisplayManagerInternal;
import android.os.IBinder;
-import android.os.IRemoteCallback;
+import android.view.animation.Animation;
import java.util.List;
@@ -85,6 +85,41 @@
}
/**
+ * Abstract class to be notified about {@link com.android.server.wm.AppTransition} events. Held
+ * as an abstract class so a listener only needs to implement the methods of its interest.
+ */
+ public static abstract class AppTransitionListener {
+
+ /**
+ * Called when an app transition is being setup and about to be executed.
+ */
+ public void onAppTransitionPendingLocked() {}
+
+ /**
+ * Called when a pending app transition gets cancelled.
+ */
+ public void onAppTransitionCancelledLocked() {}
+
+ /**
+ * Called when an app transition gets started
+ *
+ * @param openToken the token for the opening app
+ * @param closeToken the token for the closing app
+ * @param openAnimation the animation for the opening app
+ * @param closeAnimation the animation for the closing app
+ */
+ public void onAppTransitionStartingLocked(IBinder openToken, IBinder closeToken,
+ Animation openAnimation, Animation closeAnimation) {}
+
+ /**
+ * Called when an app transition is finished running.
+ *
+ * @param token the token for app whose transition has finished
+ */
+ public void onAppTransitionFinishedLocked(IBinder token) {}
+ }
+
+ /**
* Request that the window manager call
* {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager}
* within a surface transaction at a later time.
@@ -189,4 +224,11 @@
* @param removeWindows Whether to also remove the windows associated with the token.
*/
public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows);
+
+ /**
+ * Registers a listener to be notified about app transition events.
+ *
+ * @param listener The listener to register.
+ */
+ public abstract void registerAppTransitionListener(AppTransitionListener listener);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 3f35612..9199af1 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -365,6 +365,11 @@
* @return true if window is on default display.
*/
public boolean isDefaultDisplay();
+
+ /**
+ * Check whether the window is currently dimming.
+ */
+ public boolean isDimming();
}
/**
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 52912b1..d0dde00 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -40,6 +40,9 @@
private final Object mLock = new Object();
+ private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+
private final SparseArray<AccessibilityWindowInfo> mWindowCache =
new SparseArray<>();
@@ -73,9 +76,29 @@
synchronized (mLock) {
final int eventType = event.getEventType();
switch (eventType) {
- case AccessibilityEvent.TYPE_VIEW_FOCUSED:
- case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
- case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
+ case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+ if (mAccessibilityFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ refreshCachedNodeLocked(event.getWindowId(), mAccessibilityFocus);
+ }
+ mAccessibilityFocus = event.getSourceNodeId();
+ refreshCachedNodeLocked(event.getWindowId(), mAccessibilityFocus);
+ } break;
+
+ case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+ if (mAccessibilityFocus == event.getSourceNodeId()) {
+ refreshCachedNodeLocked(event.getWindowId(), mAccessibilityFocus);
+ mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ }
+ } break;
+
+ case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+ if (mInputFocus != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ }
+ mInputFocus = event.getSourceNodeId();
+ refreshCachedNodeLocked(event.getWindowId(), mInputFocus);
+ } break;
+
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_CLICKED:
@@ -268,6 +291,9 @@
final int windowId = mNodeCache.keyAt(i);
clearNodesForWindowLocked(windowId);
}
+
+ mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
}
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 606c83e..4d1209a 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -19,6 +19,8 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.AnimRes;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -65,7 +67,7 @@
* @return The animation object reference by the specified id
* @throws NotFoundException when the animation cannot be loaded
*/
- public static Animation loadAnimation(Context context, int id)
+ public static Animation loadAnimation(Context context, @AnimRes int id)
throws NotFoundException {
XmlResourceParser parser = null;
@@ -143,7 +145,7 @@
* @return The animation object reference by the specified id
* @throws NotFoundException when the layout animation controller cannot be loaded
*/
- public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
+ public static LayoutAnimationController loadLayoutAnimation(Context context, @AnimRes int id)
throws NotFoundException {
XmlResourceParser parser = null;
@@ -266,7 +268,8 @@
* @return The animation object reference by the specified id
* @throws NotFoundException
*/
- public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
+ public static Interpolator loadInterpolator(Context context, @InterpolatorRes int id)
+ throws NotFoundException {
XmlResourceParser parser = null;
try {
parser = context.getResources().getAnimation(id);
diff --git a/core/java/android/view/animation/ClipRectAnimation.java b/core/java/android/view/animation/ClipRectAnimation.java
index 2361501..e194927 100644
--- a/core/java/android/view/animation/ClipRectAnimation.java
+++ b/core/java/android/view/animation/ClipRectAnimation.java
@@ -26,8 +26,8 @@
* @hide
*/
public class ClipRectAnimation extends Animation {
- private Rect mFromRect = new Rect();
- private Rect mToRect = new Rect();
+ protected Rect mFromRect = new Rect();
+ protected Rect mToRect = new Rect();
/**
* Constructor to use when building a ClipRectAnimation from code
@@ -43,6 +43,15 @@
mToRect.set(toClip);
}
+ /**
+ * Constructor to use when building a ClipRectAnimation from code
+ */
+ public ClipRectAnimation(int fromL, int fromT, int fromR, int fromB,
+ int toL, int toT, int toR, int toB) {
+ mFromRect.set(fromL, fromT, fromR, fromB);
+ mToRect.set(toL, toT, toR, toB);
+ }
+
@Override
protected void applyTransformation(float it, Transformation tr) {
int l = mFromRect.left + (int) ((mToRect.left - mFromRect.left) * it);
diff --git a/core/java/android/view/animation/ClipRectLRAnimation.java b/core/java/android/view/animation/ClipRectLRAnimation.java
new file mode 100644
index 0000000..8993cd3
--- /dev/null
+++ b/core/java/android/view/animation/ClipRectLRAnimation.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+
+import android.graphics.Rect;
+
+/**
+ * Special case of ClipRectAnimation that animates only the left/right
+ * dimensions of the clip, picking up the other dimensions from whatever is
+ * set on the transform already.
+ *
+ * @hide
+ */
+public class ClipRectLRAnimation extends ClipRectAnimation {
+
+ /**
+ * Constructor. Passes in 0 for Top/Bottom parameters of ClipRectAnimation
+ */
+ public ClipRectLRAnimation(int fromL, int fromR, int toL, int toR) {
+ super(fromL, 0, fromR, 0, toL, 0, toR, 0);
+ }
+
+ /**
+ * Calculates and sets clip rect on given transformation. It uses existing values
+ * on the Transformation for Top/Bottom clip parameters.
+ */
+ @Override
+ protected void applyTransformation(float it, Transformation tr) {
+ Rect oldClipRect = tr.getClipRect();
+ tr.setClipRect(mFromRect.left + (int) ((mToRect.left - mFromRect.left) * it),
+ oldClipRect.top,
+ mFromRect.right + (int) ((mToRect.right - mFromRect.right) * it),
+ oldClipRect.bottom);
+ }
+}
diff --git a/core/java/android/view/animation/ClipRectTBAnimation.java b/core/java/android/view/animation/ClipRectTBAnimation.java
new file mode 100644
index 0000000..06f86ce
--- /dev/null
+++ b/core/java/android/view/animation/ClipRectTBAnimation.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+
+import android.graphics.Rect;
+
+/**
+ * Special case of ClipRectAnimation that animates only the top/bottom
+ * dimensions of the clip, picking up the other dimensions from whatever is
+ * set on the transform already.
+ *
+ * @hide
+ */
+public class ClipRectTBAnimation extends ClipRectAnimation {
+
+ /**
+ * Constructor. Passes in 0 for Left/Right parameters of ClipRectAnimation
+ */
+ public ClipRectTBAnimation(int fromT, int fromB, int toT, int toB) {
+ super(0, fromT, 0, fromB, 0, toT, 0, toB);
+ }
+
+ /**
+ * Calculates and sets clip rect on given transformation. It uses existing values
+ * on the Transformation for Left/Right clip parameters.
+ */
+ @Override
+ protected void applyTransformation(float it, Transformation tr) {
+ Rect oldClipRect = tr.getClipRect();
+ tr.setClipRect(oldClipRect.left, mFromRect.top + (int) ((mToRect.top - mFromRect.top) * it),
+ oldClipRect.right,
+ mFromRect.bottom + (int) ((mToRect.bottom - mFromRect.bottom) * it));
+ }
+
+}
diff --git a/core/java/android/view/animation/Transformation.java b/core/java/android/view/animation/Transformation.java
index 2f4fe73..30c12ed 100644
--- a/core/java/android/view/animation/Transformation.java
+++ b/core/java/android/view/animation/Transformation.java
@@ -122,7 +122,13 @@
mAlpha *= t.getAlpha();
mMatrix.preConcat(t.getMatrix());
if (t.mHasClipRect) {
- setClipRect(t.getClipRect());
+ Rect bounds = t.getClipRect();
+ if (mHasClipRect) {
+ setClipRect(mClipRect.left + bounds.left, mClipRect.top + bounds.top,
+ mClipRect.right + bounds.right, mClipRect.bottom + bounds.bottom);
+ } else {
+ setClipRect(bounds);
+ }
}
}
@@ -135,7 +141,13 @@
mAlpha *= t.getAlpha();
mMatrix.postConcat(t.getMatrix());
if (t.mHasClipRect) {
- setClipRect(t.getClipRect());
+ Rect bounds = t.getClipRect();
+ if (mHasClipRect) {
+ setClipRect(mClipRect.left + bounds.left, mClipRect.top + bounds.top,
+ mClipRect.right + bounds.right, mClipRect.bottom + bounds.bottom);
+ } else {
+ setClipRect(bounds);
+ }
}
}
diff --git a/core/java/android/view/animation/TranslateAnimation.java b/core/java/android/view/animation/TranslateAnimation.java
index d2ff754..216022b 100644
--- a/core/java/android/view/animation/TranslateAnimation.java
+++ b/core/java/android/view/animation/TranslateAnimation.java
@@ -24,7 +24,7 @@
* An animation that controls the position of an object. See the
* {@link android.view.animation full package} description for details and
* sample code.
- *
+ *
*/
public class TranslateAnimation extends Animation {
private int mFromXType = ABSOLUTE;
@@ -33,20 +33,28 @@
private int mFromYType = ABSOLUTE;
private int mToYType = ABSOLUTE;
- private float mFromXValue = 0.0f;
- private float mToXValue = 0.0f;
+ /** @hide */
+ protected float mFromXValue = 0.0f;
+ /** @hide */
+ protected float mToXValue = 0.0f;
- private float mFromYValue = 0.0f;
- private float mToYValue = 0.0f;
+ /** @hide */
+ protected float mFromYValue = 0.0f;
+ /** @hide */
+ protected float mToYValue = 0.0f;
- private float mFromXDelta;
- private float mToXDelta;
- private float mFromYDelta;
- private float mToYDelta;
+ /** @hide */
+ protected float mFromXDelta;
+ /** @hide */
+ protected float mToXDelta;
+ /** @hide */
+ protected float mFromYDelta;
+ /** @hide */
+ protected float mToYDelta;
/**
* Constructor used when a TranslateAnimation is loaded from a resource.
- *
+ *
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
@@ -81,7 +89,7 @@
/**
* Constructor to use when building a TranslateAnimation from code
- *
+ *
* @param fromXDelta Change in X coordinate to apply at the start of the
* animation
* @param toXDelta Change in X coordinate to apply at the end of the
diff --git a/core/java/android/view/animation/TranslateXAnimation.java b/core/java/android/view/animation/TranslateXAnimation.java
new file mode 100644
index 0000000..d75323f
--- /dev/null
+++ b/core/java/android/view/animation/TranslateXAnimation.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+
+import android.graphics.Matrix;
+
+/**
+ * Special case of TranslateAnimation that translates only horizontally, picking up the
+ * vertical values from whatever is set on the Transformation already. When used in
+ * conjunction with a TranslateYAnimation, allows independent animation of x and y
+ * position.
+ * @hide
+ */
+public class TranslateXAnimation extends TranslateAnimation {
+ float[] mTmpValues = new float[9];
+
+ /**
+ * Constructor. Passes in 0 for the y parameters of TranslateAnimation
+ */
+ public TranslateXAnimation(float fromXDelta, float toXDelta) {
+ super(fromXDelta, toXDelta, 0, 0);
+ }
+
+ /**
+ * Constructor. Passes in 0 for the y parameters of TranslateAnimation
+ */
+ public TranslateXAnimation(int fromXType, float fromXValue, int toXType, float toXValue) {
+ super(fromXType, fromXValue, toXType, toXValue, ABSOLUTE, 0, ABSOLUTE, 0);
+ }
+
+ /**
+ * Calculates and sets x translation values on given transformation.
+ */
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ Matrix m = t.getMatrix();
+ m.getValues(mTmpValues);
+ float dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
+ t.getMatrix().setTranslate(dx, mTmpValues[Matrix.MTRANS_Y]);
+ }
+}
diff --git a/core/java/android/view/animation/TranslateYAnimation.java b/core/java/android/view/animation/TranslateYAnimation.java
new file mode 100644
index 0000000..714558d
--- /dev/null
+++ b/core/java/android/view/animation/TranslateYAnimation.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.animation;
+
+import android.graphics.Matrix;
+
+/**
+ * Special case of TranslateAnimation that translates only vertically, picking up the
+ * horizontal values from whatever is set on the Transformation already. When used in
+ * conjunction with a TranslateXAnimation, allows independent animation of x and y
+ * position.
+ * @hide
+ */
+public class TranslateYAnimation extends TranslateAnimation {
+ float[] mTmpValues = new float[9];
+
+ /**
+ * Constructor. Passes in 0 for the x parameters of TranslateAnimation
+ */
+ public TranslateYAnimation(float fromYDelta, float toYDelta) {
+ super(0, 0, fromYDelta, toYDelta);
+ }
+
+ /**
+ * Constructor. Passes in 0 for the x parameters of TranslateAnimation
+ */
+ public TranslateYAnimation(int fromYType, float fromYValue, int toYType, float toYValue) {
+ super(ABSOLUTE, 0, ABSOLUTE, 0, fromYType, fromYValue, toYType, toYValue);
+ }
+
+ /**
+ * Calculates and sets y translation values on given transformation.
+ */
+ @Override
+ protected void applyTransformation(float interpolatedTime, Transformation t) {
+ Matrix m = t.getMatrix();
+ m.getValues(mTmpValues);
+ float dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
+ t.getMatrix().setTranslate(mTmpValues[Matrix.MTRANS_X], dy);
+ }
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index b56378f..325ffdd 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -494,19 +494,17 @@
mIInputContext.finishComposingText();
} catch (RemoteException e) {
}
- // Check focus again in case that "onWindowFocus" is called before
- // handling this message.
- if (mServedView != null && mServedView.hasWindowFocus()) {
- // "finishComposingText" has been already called above. So we
- // should not call mServedInputConnection.finishComposingText here.
- // Also, please note that this handler thread could be different
- // from a thread that created mServedView. That could happen
- // the current activity is running in the system process.
- // In that case, we really should not call
- // mServedInputConnection.finishComposingText.
- if (checkFocusNoStartInput(mHasBeenInactive, false)) {
- startInputInner(null, 0, 0, 0);
- }
+ }
+ // Check focus again in case that "onWindowFocus" is called before
+ // handling this message.
+ if (mServedView != null && mServedView.hasWindowFocus()) {
+ // Please note that this handler thread could be different
+ // from a thread that created mServedView. That could happen
+ // the current activity is running in the system process.
+ // In that case, we really should not call
+ // mServedInputConnection.finishComposingText.
+ if (checkFocusNoStartInput(mHasBeenInactive, false)) {
+ startInputInner(null, 0, 0, 0);
}
}
}
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 1671faa..c2f3777 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -23,6 +23,8 @@
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.inputmethod.InputMethodUtils;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -379,7 +381,7 @@
*/
public CharSequence getDisplayName(
Context context, String packageName, ApplicationInfo appInfo) {
- final Locale locale = constructLocaleFromString(mSubtypeLocale);
+ final Locale locale = InputMethodUtils.constructLocaleFromString(mSubtypeLocale);
final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
if (mSubtypeNameResId == 0) {
return localeStr;
@@ -503,22 +505,6 @@
}
};
- private static Locale constructLocaleFromString(String localeStr) {
- if (TextUtils.isEmpty(localeStr))
- return null;
- String[] localeParams = localeStr.split("_", 3);
- // The length of localeStr is guaranteed to always return a 1 <= value <= 3
- // because localeStr is not empty.
- if (localeParams.length == 1) {
- return new Locale(localeParams[0]);
- } else if (localeParams.length == 2) {
- return new Locale(localeParams[0], localeParams[1]);
- } else if (localeParams.length == 3) {
- return new Locale(localeParams[0], localeParams[1], localeParams[2]);
- }
- return null;
- }
-
private static int hashCodeInternal(String locale, String mode, String extraValue,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
boolean isAsciiCapable) {
diff --git a/core/java/android/webkit/LegacyErrorStrings.java b/core/java/android/webkit/LegacyErrorStrings.java
index 11fc05d..60a6ee1 100644
--- a/core/java/android/webkit/LegacyErrorStrings.java
+++ b/core/java/android/webkit/LegacyErrorStrings.java
@@ -17,7 +17,6 @@
package android.webkit;
import android.content.Context;
-import android.net.http.EventHandler;
import android.util.Log;
/**
@@ -44,52 +43,52 @@
*/
private static int getResource(int errorCode) {
switch(errorCode) {
- case EventHandler.OK:
+ case 0: /* EventHandler.OK: */
return com.android.internal.R.string.httpErrorOk;
- case EventHandler.ERROR:
+ case -1: /* EventHandler.ERROR: */
return com.android.internal.R.string.httpError;
- case EventHandler.ERROR_LOOKUP:
+ case -2: /* EventHandler.ERROR_LOOKUP: */
return com.android.internal.R.string.httpErrorLookup;
- case EventHandler.ERROR_UNSUPPORTED_AUTH_SCHEME:
+ case -3: /* EventHandler.ERROR_UNSUPPORTED_AUTH_SCHEME: */
return com.android.internal.R.string.httpErrorUnsupportedAuthScheme;
- case EventHandler.ERROR_AUTH:
+ case -4: /* EventHandler.ERROR_AUTH: */
return com.android.internal.R.string.httpErrorAuth;
- case EventHandler.ERROR_PROXYAUTH:
+ case -5: /* EventHandler.ERROR_PROXYAUTH: */
return com.android.internal.R.string.httpErrorProxyAuth;
- case EventHandler.ERROR_CONNECT:
+ case -6: /* EventHandler.ERROR_CONNECT: */
return com.android.internal.R.string.httpErrorConnect;
- case EventHandler.ERROR_IO:
+ case -7: /* EventHandler.ERROR_IO: */
return com.android.internal.R.string.httpErrorIO;
- case EventHandler.ERROR_TIMEOUT:
+ case -8: /* EventHandler.ERROR_TIMEOUT: */
return com.android.internal.R.string.httpErrorTimeout;
- case EventHandler.ERROR_REDIRECT_LOOP:
+ case -9: /* EventHandler.ERROR_REDIRECT_LOOP: */
return com.android.internal.R.string.httpErrorRedirectLoop;
- case EventHandler.ERROR_UNSUPPORTED_SCHEME:
+ case -10: /* EventHandler.ERROR_UNSUPPORTED_SCHEME: */
return com.android.internal.R.string.httpErrorUnsupportedScheme;
- case EventHandler.ERROR_FAILED_SSL_HANDSHAKE:
+ case -11: /* EventHandler.ERROR_FAILED_SSL_HANDSHAKE: */
return com.android.internal.R.string.httpErrorFailedSslHandshake;
- case EventHandler.ERROR_BAD_URL:
+ case -12: /* EventHandler.ERROR_BAD_URL: */
return com.android.internal.R.string.httpErrorBadUrl;
- case EventHandler.FILE_ERROR:
+ case -13: /* EventHandler.FILE_ERROR: */
return com.android.internal.R.string.httpErrorFile;
- case EventHandler.FILE_NOT_FOUND_ERROR:
+ case -14: /* EventHandler.FILE_NOT_FOUND_ERROR: */
return com.android.internal.R.string.httpErrorFileNotFound;
- case EventHandler.TOO_MANY_REQUESTS_ERROR:
+ case -15: /* EventHandler.TOO_MANY_REQUESTS_ERROR: */
return com.android.internal.R.string.httpErrorTooManyRequests;
default:
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index e87a117..164283d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -2712,7 +2713,7 @@
*
* @attr ref android.R.styleable#AbsListView_listSelector
*/
- public void setSelector(int resID) {
+ public void setSelector(@DrawableRes int resID) {
setSelector(getContext().getDrawable(resID));
}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 78344ac..79ad6e3 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -423,8 +423,8 @@
}
if (track != null) {
- track.setBounds(0, trackOffset, w - mPaddingRight - mPaddingLeft,
- h - mPaddingBottom - trackOffset - mPaddingTop);
+ final int trackWidth = w - mPaddingRight - mPaddingLeft;
+ track.setBounds(0, trackOffset, trackWidth, trackOffset + trackHeight);
}
if (thumb != null) {
@@ -472,7 +472,6 @@
final Drawable background = getBackground();
if (background != null) {
- final Rect bounds = thumb.getBounds();
final int offsetX = mPaddingLeft - mThumbOffset;
final int offsetY = mPaddingTop;
background.setHotspotBounds(left + offsetX, top + offsetY,
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index f9af2f9..f34ad71 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -334,7 +335,7 @@
*
* @param resourceId The content description resource id.
*/
- public void setExpandActivityOverflowButtonContentDescription(int resourceId) {
+ public void setExpandActivityOverflowButtonContentDescription(@StringRes int resourceId) {
CharSequence contentDescription = mContext.getString(resourceId);
mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
}
@@ -514,7 +515,7 @@
*
* @param resourceId The resource id.
*/
- public void setDefaultActionButtonContentDescription(int resourceId) {
+ public void setDefaultActionButtonContentDescription(@StringRes int resourceId) {
mDefaultActionButtonContentDescription = resourceId;
}
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index aff5e29..89e508f 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -16,6 +16,9 @@
package android.widget;
+import android.annotation.ArrayRes;
+import android.annotation.IdRes;
+import android.annotation.LayoutRes;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
@@ -106,7 +109,7 @@
* @param resource The resource ID for a layout file containing a TextView to use when
* instantiating views.
*/
- public ArrayAdapter(Context context, int resource) {
+ public ArrayAdapter(Context context, @LayoutRes int resource) {
this(context, resource, 0, new ArrayList<T>());
}
@@ -118,7 +121,7 @@
* instantiating views.
* @param textViewResourceId The id of the TextView within the layout resource to be populated
*/
- public ArrayAdapter(Context context, int resource, int textViewResourceId) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId) {
this(context, resource, textViewResourceId, new ArrayList<T>());
}
@@ -130,7 +133,7 @@
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, T[] objects) {
this(context, resource, 0, Arrays.asList(objects));
}
@@ -143,7 +146,7 @@
* @param textViewResourceId The id of the TextView within the layout resource to be populated
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId, T[] objects) {
this(context, resource, textViewResourceId, Arrays.asList(objects));
}
@@ -155,7 +158,7 @@
* instantiating views.
* @param objects The objects to represent in the ListView.
*/
- public ArrayAdapter(Context context, int resource, List<T> objects) {
+ public ArrayAdapter(Context context, @LayoutRes int resource, List<T> objects) {
this(context, resource, 0, objects);
}
@@ -405,7 +408,7 @@
* @param resource the layout resource defining the drop down views
* @see #getDropDownView(int, android.view.View, android.view.ViewGroup)
*/
- public void setDropDownViewResource(int resource) {
+ public void setDropDownViewResource(@LayoutRes int resource) {
this.mDropDownResource = resource;
}
@@ -457,7 +460,7 @@
* @return An ArrayAdapter<CharSequence>.
*/
public static ArrayAdapter<CharSequence> createFromResource(Context context,
- int textArrayResId, int textViewResId) {
+ @ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
return new ArrayAdapter<CharSequence>(context, textViewResId, strings);
}
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index e6392b9..01767d5 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
@@ -356,7 +357,7 @@
*
* @attr ref android.R.styleable#PopupWindow_popupBackground
*/
- public void setDropDownBackgroundResource(int id) {
+ public void setDropDownBackgroundResource(@DrawableRes int id) {
mPopup.setBackgroundDrawable(getContext().getDrawable(id));
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 5e43916..47fb8a7 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.Configuration;
@@ -253,7 +254,7 @@
*
* @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
*/
- public void setSelectedDateVerticalBar(int resourceId) {
+ public void setSelectedDateVerticalBar(@DrawableRes int resourceId) {
mDelegate.setSelectedDateVerticalBar(resourceId);
}
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 344d00a..84f0ee5 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -32,7 +33,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-
/**
* An extension to TextView that supports the {@link android.widget.Checkable} interface.
* This is useful when used in a {@link android.widget.ListView ListView} where the it's
@@ -141,7 +141,7 @@
*
* @attr ref android.R.styleable#CheckedTextView_checkMark
*/
- public void setCheckMarkDrawable(int resid) {
+ public void setCheckMarkDrawable(@DrawableRes int resid) {
if (resid != 0 && resid == mCheckMarkResource) {
return;
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index fede493..dbf82b6 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -16,10 +16,12 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.graphics.PorterDuff;
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
@@ -50,7 +52,6 @@
*/
public abstract class CompoundButton extends Button implements Checkable {
private boolean mChecked;
- private int mButtonResource;
private boolean mBroadcasting;
private Drawable mButtonDrawable;
@@ -197,54 +198,62 @@
}
/**
- * Set the button graphic to a given Drawable, identified by its resource
- * id.
+ * Sets a drawable as the compound button image given its resource
+ * identifier.
*
- * @param resid the resource id of the drawable to use as the button
- * graphic
+ * @param resId the resource identifier of the drawable
+ * @attr ref android.R.styleable#CompoundButton_button
*/
- public void setButtonDrawable(int resid) {
- if (resid != 0 && resid == mButtonResource) {
- return;
- }
-
- mButtonResource = resid;
-
- Drawable d = null;
- if (mButtonResource != 0) {
- d = getContext().getDrawable(mButtonResource);
+ public void setButtonDrawable(@DrawableRes int resId) {
+ final Drawable d;
+ if (resId != 0) {
+ d = getContext().getDrawable(resId);
+ } else {
+ d = null;
}
setButtonDrawable(d);
}
/**
- * Set the button graphic to a given Drawable
+ * Sets a drawable as the compound button image.
*
- * @param d The Drawable to use as the button graphic
+ * @param drawable the drawable to set
+ * @attr ref android.R.styleable#CompoundButton_button
*/
- public void setButtonDrawable(Drawable d) {
- if (mButtonDrawable != d) {
+ @Nullable
+ public void setButtonDrawable(@Nullable Drawable drawable) {
+ if (mButtonDrawable != drawable) {
if (mButtonDrawable != null) {
mButtonDrawable.setCallback(null);
unscheduleDrawable(mButtonDrawable);
}
- mButtonDrawable = d;
+ mButtonDrawable = drawable;
- if (d != null) {
- d.setCallback(this);
- d.setLayoutDirection(getLayoutDirection());
- if (d.isStateful()) {
- d.setState(getDrawableState());
+ if (drawable != null) {
+ drawable.setCallback(this);
+ drawable.setLayoutDirection(getLayoutDirection());
+ if (drawable.isStateful()) {
+ drawable.setState(getDrawableState());
}
- d.setVisible(getVisibility() == VISIBLE, false);
- setMinHeight(d.getIntrinsicHeight());
+ drawable.setVisible(getVisibility() == VISIBLE, false);
+ setMinHeight(drawable.getIntrinsicHeight());
applyButtonTint();
}
}
}
/**
+ * @return the drawable used as the compound button image
+ * @see #setButtonDrawable(Drawable)
+ * @see #setButtonDrawable(int)
+ */
+ @Nullable
+ public Drawable getButtonDrawable() {
+ return mButtonDrawable;
+ }
+
+ /**
* Applies a tint to the button drawable. Does not modify the current tint
* mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
* <p>
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 85b4d30..a053901 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -192,6 +192,7 @@
mYearPickerView = new YearPickerView(mContext);
mYearPickerView.init(this);
+ mYearPickerView.setRange(mMinDate, mMaxDate);
final ColorStateList yearBackgroundColor = a.getColorStateList(
R.styleable.DatePicker_yearListSelectorColor);
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 6925756..391347e 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -24,7 +24,6 @@
import android.content.Context;
import android.graphics.Canvas;
-import android.util.FloatMath;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -220,8 +219,8 @@
if (mPullDistance == 0) {
mGlowScaleY = mGlowScaleYStart = 0;
} else {
- final float scale = Math.max(0, 1 - 1 /
- FloatMath.sqrt(Math.abs(mPullDistance) * mBounds.height()) - 0.3f) / 0.7f;
+ final float scale = (float) (Math.max(0, 1 - 1 /
+ Math.sqrt(Math.abs(mPullDistance) * mBounds.height()) - 0.3d) / 0.7d);
mGlowScaleY = mGlowScaleYStart = scale;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index d5166f3..1ba11da 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -50,6 +50,7 @@
import android.inputmethodservice.ExtractEditText;
import android.os.Bundle;
import android.os.Handler;
+import android.os.ParcelableParcel;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.DynamicLayout;
@@ -118,15 +119,18 @@
*/
public class Editor {
private static final String TAG = "Editor";
- static final boolean DEBUG_UNDO = false;
+ private static final boolean DEBUG_UNDO = false;
static final int BLINK = 500;
private static final float[] TEMP_POSITION = new float[2];
private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20;
+ // Tag used when the Editor maintains its own separate UndoManager.
+ private static final String UNDO_OWNER_TAG = "Editor";
- UndoManager mUndoManager;
- UndoOwner mUndoOwner;
- InputFilter mUndoInputFilter;
+ // Each Editor manages its own undo stack.
+ private final UndoManager mUndoManager = new UndoManager();
+ private UndoOwner mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
+ final InputFilter mUndoInputFilter = new UndoInputFilter(this);
// Cursor Controllers.
InsertionPointCursorController mInsertionPointCursorController;
@@ -222,6 +226,39 @@
Editor(TextView textView) {
mTextView = textView;
+ // Synchronize the filter list, which places the undo input filter at the end.
+ mTextView.setFilters(mTextView.getFilters());
+ }
+
+ ParcelableParcel saveInstanceState() {
+ // For now there is only undo state.
+ return (ParcelableParcel) mUndoManager.saveInstanceState();
+ }
+
+ void restoreInstanceState(ParcelableParcel state) {
+ mUndoManager.restoreInstanceState(state);
+ // Re-associate this object as the owner of undo state.
+ mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
+ }
+
+ boolean canUndo() {
+ UndoOwner[] owners = { mUndoOwner };
+ return mUndoManager.countUndos(owners) > 0;
+ }
+
+ boolean canRedo() {
+ UndoOwner[] owners = { mUndoOwner };
+ return mUndoManager.countRedos(owners) > 0;
+ }
+
+ void undo() {
+ UndoOwner[] owners = { mUndoOwner };
+ mUndoManager.undo(owners, 1); // Undo 1 action.
+ }
+
+ void redo() {
+ UndoOwner[] owners = { mUndoOwner };
+ mUndoManager.redo(owners, 1); // Redo 1 action.
}
void onAttachedToWindow() {
@@ -1352,6 +1389,9 @@
searchStartIndex);
// Note how dynamic layout's internal block indices get updated from Editor
blockIndices[i] = blockIndex;
+ if (mTextDisplayLists[blockIndex] != null) {
+ mTextDisplayLists[blockIndex].isDirty = true;
+ }
searchStartIndex = blockIndex + 1;
}
@@ -1388,6 +1428,7 @@
// brings this range of text back to the top left corner of the viewport
hardwareCanvas.translate(-left, -top);
layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine);
+ mTextDisplayLists[blockIndex].isDirty = false;
// No need to untranslate, previous context is popped after
// drawDisplayList
} finally {
@@ -1702,7 +1743,7 @@
/**
* Called by the framework in response to a text auto-correction (such as fixing a typo using a
- * a dictionnary) from the current input method, provided by it calling
+ * a dictionary) from the current input method, provided by it calling
* {@link InputConnection#commitCorrection} InputConnection.commitCorrection()}. The default
* implementation flashes the background of the corrected word to provide feedback to the user.
*
@@ -4157,8 +4198,19 @@
int mChangedStart, mChangedEnd, mChangedDelta;
}
+ /**
+ * @return True iff (start, end) is a valid range within the text.
+ */
+ private static boolean isValidRange(CharSequence text, int start, int end) {
+ return 0 <= start && start <= end && end <= text.length();
+ }
+
+ /**
+ * An InputFilter that monitors text input to maintain undo history. It does not modify the
+ * text being typed (and hence always returns null from the filter() method).
+ */
public static class UndoInputFilter implements InputFilter {
- final Editor mEditor;
+ private final Editor mEditor;
public UndoInputFilter(Editor editor) {
mEditor = editor;
@@ -4168,92 +4220,123 @@
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
if (DEBUG_UNDO) {
- Log.d(TAG, "filter: source=" + source + " (" + start + "-" + end + ")");
- Log.d(TAG, "filter: dest=" + dest + " (" + dstart + "-" + dend + ")");
+ Log.d(TAG, "filter: source=" + source + " (" + start + "-" + end + ") " +
+ "dest=" + dest + " (" + dstart + "-" + dend + ")");
}
final UndoManager um = mEditor.mUndoManager;
if (um.isInUndo()) {
- if (DEBUG_UNDO) Log.d(TAG, "*** skipping, currently performing undo/redo");
+ if (DEBUG_UNDO) Log.d(TAG, "filter: skipping, currently performing undo/redo");
return null;
}
+ // Text filters run before input operations are applied. However, some input operations
+ // are invalid and will throw exceptions when applied. This is common in tests. Don't
+ // attempt to undo invalid operations.
+ if (!isValidRange(source, start, end) || !isValidRange(dest, dstart, dend)) {
+ if (DEBUG_UNDO) Log.d(TAG, "filter: invalid op");
+ return null;
+ }
+
+ // Earlier filters can rewrite input to be a no-op, for example due to a length limit
+ // on an input field. Skip no-op changes.
+ if (start == end && dstart == dend) {
+ if (DEBUG_UNDO) Log.d(TAG, "filter: skipping no-op");
+ return null;
+ }
+
+ // Build a new operation with all the information from this edit.
+ EditOperation edit = new EditOperation(mEditor, source, start, end, dest, dstart, dend);
+
+ // Fetch the last edit operation and attempt to merge in the new edit.
um.beginUpdate("Edit text");
- TextModifyOperation op = um.getLastOperation(
- TextModifyOperation.class, mEditor.mUndoOwner, UndoManager.MERGE_MODE_UNIQUE);
- if (op != null) {
- if (DEBUG_UNDO) Log.d(TAG, "Last op: range=(" + op.mRangeStart + "-" + op.mRangeEnd
- + "), oldText=" + op.mOldText);
- // See if we can continue modifying this operation.
- if (op.mOldText == null) {
- // The current operation is an add... are we adding more? We are adding
- // more if we are either appending new text to the end of the last edit or
- // completely replacing some or all of the last edit.
- if (start < end && ((dstart >= op.mRangeStart && dend <= op.mRangeEnd)
- || (dstart == op.mRangeEnd && dend == op.mRangeEnd))) {
- op.mRangeEnd = dstart + (end-start);
- um.endUpdate();
- if (DEBUG_UNDO) Log.d(TAG, "*** merging with last op, mRangeEnd="
- + op.mRangeEnd);
- return null;
- }
- } else {
- // The current operation is a delete... can we delete more?
- if (start == end && dend == op.mRangeStart-1) {
- SpannableStringBuilder str;
- if (op.mOldText instanceof SpannableString) {
- str = (SpannableStringBuilder)op.mOldText;
- } else {
- str = new SpannableStringBuilder(op.mOldText);
- }
- str.insert(0, dest, dstart, dend);
- op.mRangeStart = dstart;
- op.mOldText = str;
- um.endUpdate();
- if (DEBUG_UNDO) Log.d(TAG, "*** merging with last op, range=("
- + op.mRangeStart + "-" + op.mRangeEnd
- + "), oldText=" + op.mOldText);
- return null;
- }
- }
-
- // Couldn't add to the current undo operation, need to start a new
- // undo state for a new undo operation.
- um.commitState(null);
- um.setUndoLabel("Edit text");
- }
-
- // Create a new undo state reflecting the operation being performed.
- op = new TextModifyOperation(mEditor.mUndoOwner);
- op.mRangeStart = dstart;
- if (start < end) {
- op.mRangeEnd = dstart + (end-start);
+ EditOperation lastEdit = um.getLastOperation(
+ EditOperation.class, mEditor.mUndoOwner, UndoManager.MERGE_MODE_UNIQUE);
+ if (lastEdit == null) {
+ // Add this as the first edit.
+ if (DEBUG_UNDO) Log.d(TAG, "filter: adding first op " + edit);
+ um.addOperation(edit, UndoManager.MERGE_MODE_NONE);
+ } else if (lastEdit.mergeWith(edit)) {
+ // Merge succeeded, nothing else to do.
+ if (DEBUG_UNDO) Log.d(TAG, "filter: merge succeeded, created " + lastEdit);
} else {
- op.mRangeEnd = dstart;
+ // Could not merge with the last edit, so commit the last edit and add this edit.
+ if (DEBUG_UNDO) Log.d(TAG, "filter: merge failed, adding " + edit);
+ um.commitState(mEditor.mUndoOwner);
+ um.addOperation(edit, UndoManager.MERGE_MODE_NONE);
}
- if (dstart < dend) {
- op.mOldText = dest.subSequence(dstart, dend);
- }
- if (DEBUG_UNDO) Log.d(TAG, "*** adding new op, range=(" + op.mRangeStart
- + "-" + op.mRangeEnd + "), oldText=" + op.mOldText);
- um.addOperation(op, UndoManager.MERGE_MODE_NONE);
um.endUpdate();
- return null;
+ return null; // Text not changed.
}
}
- public static class TextModifyOperation extends UndoOperation<TextView> {
- int mRangeStart, mRangeEnd;
- CharSequence mOldText;
+ /**
+ * An operation to undo a single "edit" to a text view.
+ */
+ public static class EditOperation extends UndoOperation<Editor> {
+ private static final int TYPE_INSERT = 0;
+ private static final int TYPE_DELETE = 1;
+ private static final int TYPE_REPLACE = 2;
- public TextModifyOperation(UndoOwner owner) {
- super(owner);
+ private int mType;
+ private String mOldText;
+ private int mOldTextStart;
+ private String mNewText;
+ private int mNewTextStart;
+
+ private int mOldCursorPos;
+ private int mNewCursorPos;
+
+ /**
+ * Constructs an edit operation from a text input operation that replaces the range
+ * (dstart, dend) of dest with (start, end) of source. See {@link InputFilter#filter}.
+ */
+ public EditOperation(Editor editor, CharSequence source, int start, int end,
+ Spanned dest, int dstart, int dend) {
+ super(editor.mUndoOwner);
+
+ mOldText = dest.subSequence(dstart, dend).toString();
+ mNewText = source.subSequence(start, end).toString();
+
+ // Determine the type of the edit and store where it occurred. Avoid storing
+ // irrevelant data (e.g. mNewTextStart for a delete) because that makes the
+ // merging logic more complex (e.g. merging deletes could lead to mNewTextStart being
+ // outside the bounds of the final text).
+ if (mNewText.length() > 0 && mOldText.length() == 0) {
+ mType = TYPE_INSERT;
+ mNewTextStart = dstart;
+ } else if (mNewText.length() == 0 && mOldText.length() > 0) {
+ mType = TYPE_DELETE;
+ mOldTextStart = dstart;
+ } else {
+ mType = TYPE_REPLACE;
+ mOldTextStart = mNewTextStart = dstart;
+ }
+
+ // Store cursor data.
+ mOldCursorPos = editor.mTextView.getSelectionStart();
+ mNewCursorPos = dstart + (end - start);
}
- public TextModifyOperation(Parcel src, ClassLoader loader) {
+ public EditOperation(Parcel src, ClassLoader loader) {
super(src, loader);
- mRangeStart = src.readInt();
- mRangeEnd = src.readInt();
- mOldText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(src);
+ mType = src.readInt();
+ mOldText = src.readString();
+ mOldTextStart = src.readInt();
+ mNewText = src.readString();
+ mNewTextStart = src.readInt();
+ mOldCursorPos = src.readInt();
+ mNewCursorPos = src.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeString(mOldText);
+ dest.writeInt(mOldTextStart);
+ dest.writeString(mNewText);
+ dest.writeInt(mNewTextStart);
+ dest.writeInt(mOldCursorPos);
+ dest.writeInt(mNewCursorPos);
}
@Override
@@ -4262,59 +4345,139 @@
@Override
public void undo() {
- swapText();
+ if (DEBUG_UNDO) Log.d(TAG, "undo");
+ // Remove the new text and insert the old.
+ modifyText(mNewTextStart, getNewTextEnd(), mOldText, mOldTextStart, mOldCursorPos);
}
@Override
public void redo() {
- swapText();
+ if (DEBUG_UNDO) Log.d(TAG, "redo");
+ // Remove the old text and insert the new.
+ modifyText(mOldTextStart, getOldTextEnd(), mNewText, mNewTextStart, mNewCursorPos);
}
- private void swapText() {
- // Both undo and redo involves swapping the contents of the range
- // in the text view with our local text.
- TextView tv = getOwnerData();
- Editable editable = (Editable)tv.getText();
- CharSequence curText;
- if (mRangeStart >= mRangeEnd) {
- curText = null;
- } else {
- curText = editable.subSequence(mRangeStart, mRangeEnd);
+ /**
+ * Attempts to merge this existing operation with a new edit.
+ * @param edit The new edit operation.
+ * @return If the merge succeeded, returns true. Otherwise returns false and leaves this
+ * object unchanged.
+ */
+ private boolean mergeWith(EditOperation edit) {
+ switch (mType) {
+ case TYPE_INSERT:
+ return mergeInsertWith(edit);
+ case TYPE_DELETE:
+ return mergeDeleteWith(edit);
+ case TYPE_REPLACE:
+ return mergeReplaceWith(edit);
+ default:
+ return false;
}
- if (DEBUG_UNDO) {
- Log.d(TAG, "Swap: range=(" + mRangeStart + "-" + mRangeEnd
- + "), oldText=" + mOldText);
- Log.d(TAG, "Swap: curText=" + curText);
+ }
+
+ private boolean mergeInsertWith(EditOperation edit) {
+ if (DEBUG_UNDO) Log.d(TAG, "mergeInsertWith " + edit);
+ // Only merge continuous insertions.
+ if (edit.mType != TYPE_INSERT) {
+ return false;
}
- if (mOldText == null) {
- editable.delete(mRangeStart, mRangeEnd);
- mRangeEnd = mRangeStart;
- } else {
- editable.replace(mRangeStart, mRangeEnd, mOldText);
- mRangeEnd = mRangeStart + mOldText.length();
+ // Only merge insertions that are contiguous.
+ if (getNewTextEnd() != edit.mNewTextStart) {
+ return false;
}
- mOldText = curText;
+ mNewText += edit.mNewText;
+ mNewCursorPos = edit.mNewCursorPos;
+ return true;
+ }
+
+ // TODO: Support forward delete.
+ private boolean mergeDeleteWith(EditOperation edit) {
+ if (DEBUG_UNDO) Log.d(TAG, "mergeDeleteWith " + edit);
+ // Only merge continuous deletes.
+ if (edit.mType != TYPE_DELETE) {
+ return false;
+ }
+ // Only merge deletions that are contiguous.
+ if (mOldTextStart != edit.getOldTextEnd()) {
+ return false;
+ }
+ mOldTextStart = edit.mOldTextStart;
+ mOldText = edit.mOldText + mOldText;
+ mNewCursorPos = edit.mNewCursorPos;
+ return true;
+ }
+
+ private boolean mergeReplaceWith(EditOperation edit) {
+ if (DEBUG_UNDO) Log.d(TAG, "mergeReplaceWith " + edit);
+ // Replacements can merge only with adjacent inserts and adjacent replacements.
+ if (edit.mType == TYPE_DELETE ||
+ getNewTextEnd() != edit.mOldTextStart ||
+ edit.mOldTextStart != edit.mNewTextStart) {
+ return false;
+ }
+ mOldText += edit.mOldText;
+ mNewText += edit.mNewText;
+ mNewCursorPos = edit.mNewCursorPos;
+ return true;
+ }
+
+ private int getNewTextEnd() {
+ return mNewTextStart + mNewText.length();
+ }
+
+ private int getOldTextEnd() {
+ return mOldTextStart + mOldText.length();
+ }
+
+ private void modifyText(int deleteFrom, int deleteTo, CharSequence newText,
+ int newTextInsertAt, int newCursorPos) {
+ Editor editor = getOwnerData();
+ Editable text = (Editable) editor.mTextView.getText();
+ // Apply the edit if it is still valid.
+ if (isValidRange(text, deleteFrom, deleteTo) &&
+ newTextInsertAt <= text.length() - (deleteTo - deleteFrom)) {
+ if (deleteFrom != deleteTo) {
+ text.delete(deleteFrom, deleteTo);
+ }
+ if (newText.length() != 0) {
+ text.insert(newTextInsertAt, newText);
+ }
+ }
+ // Restore the cursor position.
+ // TODO: Select all the text that was undone.
+ if (newCursorPos <= text.length()) {
+ Selection.setSelection(text, newCursorPos);
+ }
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mRangeStart);
- dest.writeInt(mRangeEnd);
- TextUtils.writeToParcel(mOldText, dest, flags);
+ public String toString() {
+ return "EditOperation: [" +
+ "mType=" + mType + ", " +
+ "mOldText=" + mOldText + ", " +
+ "mOldTextStart=" + mOldTextStart + ", " +
+ "mNewText=" + mNewText + ", " +
+ "mNewTextStart=" + mNewTextStart + ", " +
+ "mOldCursorPos=" + mOldCursorPos + ", " +
+ "mNewCursorPos=" + mNewCursorPos + "]";
}
- public static final Parcelable.ClassLoaderCreator<TextModifyOperation> CREATOR
- = new Parcelable.ClassLoaderCreator<TextModifyOperation>() {
- public TextModifyOperation createFromParcel(Parcel in) {
- return new TextModifyOperation(in, null);
+ public static final Parcelable.ClassLoaderCreator<EditOperation> CREATOR
+ = new Parcelable.ClassLoaderCreator<EditOperation>() {
+ @Override
+ public EditOperation createFromParcel(Parcel in) {
+ return new EditOperation(in, null);
}
- public TextModifyOperation createFromParcel(Parcel in, ClassLoader loader) {
- return new TextModifyOperation(in, loader);
+ @Override
+ public EditOperation createFromParcel(Parcel in, ClassLoader loader) {
+ return new EditOperation(in, loader);
}
- public TextModifyOperation[] newArray(int size) {
- return new TextModifyOperation[size];
+ @Override
+ public EditOperation[] newArray(int size) {
+ return new EditOperation[size];
}
};
}
diff --git a/core/java/android/widget/ImageSwitcher.java b/core/java/android/widget/ImageSwitcher.java
index 80e908a..81636a7 100644
--- a/core/java/android/widget/ImageSwitcher.java
+++ b/core/java/android/widget/ImageSwitcher.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -23,7 +24,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-
public class ImageSwitcher extends ViewSwitcher
{
public ImageSwitcher(Context context)
@@ -35,7 +35,7 @@
super(context, attrs);
}
- public void setImageResource(int resid)
+ public void setImageResource(@DrawableRes int resid)
{
ImageView image = (ImageView)this.getNextView();
image.setImageResource(resid);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index dd9bdb66..9831dca 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
@@ -387,7 +388,7 @@
* @attr ref android.R.styleable#ImageView_src
*/
@android.view.RemotableViewMethod
- public void setImageResource(int resId) {
+ public void setImageResource(@DrawableRes int resId) {
// The resource configuration may have changed, so we should always
// try to load the resource even if the resId hasn't changed.
final int oldWidth = mDrawableWidth;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 0aaef6d..f9c7faa 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -21,6 +21,7 @@
import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -3630,7 +3631,7 @@
* First look in our children, then in any header and footer views that may be scrolled off.
*/
@Override
- protected View findViewTraversal(int id) {
+ protected View findViewTraversal(@IdRes int id) {
View v;
v = super.findViewTraversal(id);
if (v == null) {
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 06ac1c3..1507dfb 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -22,6 +22,7 @@
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.SubMenuBuilder;
+import android.annotation.MenuRes;
import android.content.Context;
import android.view.Gravity;
import android.view.Menu;
@@ -205,7 +206,7 @@
* popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()).
* @param menuRes Menu resource to inflate
*/
- public void inflate(int menuRes) {
+ public void inflate(@MenuRes int menuRes) {
getMenuInflater().inflate(menuRes, mMenu);
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b0745e..03878fc 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -21,6 +21,7 @@
import com.android.internal.R;
+import android.annotation.InterpolatorRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
@@ -400,36 +401,49 @@
* traverse layer and state list drawables.
*/
private Drawable tileify(Drawable drawable, boolean clip) {
+ // TODO: This is a terrible idea that potentially destroys any drawable
+ // that extends any of these classes. We *really* need to remove this.
if (drawable instanceof LayerDrawable) {
- LayerDrawable background = (LayerDrawable) drawable;
- final int N = background.getNumberOfLayers();
- Drawable[] outDrawables = new Drawable[N];
+ final LayerDrawable orig = (LayerDrawable) drawable;
+ final int N = orig.getNumberOfLayers();
+ final Drawable[] outDrawables = new Drawable[N];
for (int i = 0; i < N; i++) {
- int id = background.getId(i);
- outDrawables[i] = tileify(background.getDrawable(i),
+ final int id = orig.getId(i);
+ outDrawables[i] = tileify(orig.getDrawable(i),
(id == R.id.progress || id == R.id.secondaryProgress));
}
- LayerDrawable newBg = new LayerDrawable(outDrawables);
-
+ final LayerDrawable clone = new LayerDrawable(outDrawables);
for (int i = 0; i < N; i++) {
- newBg.setId(i, background.getId(i));
+ clone.setId(i, orig.getId(i));
+ clone.setLayerGravity(i, orig.getLayerGravity(i));
+ clone.setLayerWidth(i, orig.getLayerWidth(i));
+ clone.setLayerHeight(i, orig.getLayerHeight(i));
+ clone.setLayerInsetLeft(i, orig.getLayerInsetLeft(i));
+ clone.setLayerInsetRight(i, orig.getLayerInsetRight(i));
+ clone.setLayerInsetTop(i, orig.getLayerInsetTop(i));
+ clone.setLayerInsetBottom(i, orig.getLayerInsetBottom(i));
+ clone.setLayerInsetStart(i, orig.getLayerInsetStart(i));
+ clone.setLayerInsetEnd(i, orig.getLayerInsetEnd(i));
}
- return newBg;
+ return clone;
+ }
- } else if (drawable instanceof StateListDrawable) {
- StateListDrawable in = (StateListDrawable) drawable;
- StateListDrawable out = new StateListDrawable();
- int numStates = in.getStateCount();
- for (int i = 0; i < numStates; i++) {
+ if (drawable instanceof StateListDrawable) {
+ final StateListDrawable in = (StateListDrawable) drawable;
+ final StateListDrawable out = new StateListDrawable();
+ final int N = in.getStateCount();
+ for (int i = 0; i < N; i++) {
out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
}
- return out;
- } else if (drawable instanceof BitmapDrawable) {
+ return out;
+ }
+
+ if (drawable instanceof BitmapDrawable) {
final BitmapDrawable bitmap = (BitmapDrawable) drawable;
final Bitmap tileBitmap = bitmap.getBitmap();
if (mSampleTile == null) {
@@ -1508,7 +1522,7 @@
* @param context The application environment
* @param resID The resource identifier of the interpolator to load
*/
- public void setInterpolator(Context context, int resID) {
+ public void setInterpolator(Context context, @InterpolatorRes int resID) {
setInterpolator(AnimationUtils.loadInterpolator(context, resID));
}
@@ -1647,7 +1661,7 @@
// rotates properly in its animation
final int saveCount = canvas.save();
- if(isLayoutRtl() && mMirrorForRtl) {
+ if (isLayoutRtl() && mMirrorForRtl) {
canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
canvas.scale(-1.0f, 1.0f);
} else {
@@ -1679,20 +1693,23 @@
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- Drawable d = mCurrentDrawable;
-
int dw = 0;
int dh = 0;
+
+ final Drawable d = mCurrentDrawable;
if (d != null) {
dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
}
+
updateDrawableState();
+
dw += mPaddingLeft + mPaddingRight;
dh += mPaddingTop + mPaddingBottom;
- setMeasuredDimension(resolveSizeAndState(dw, widthMeasureSpec, 0),
- resolveSizeAndState(dh, heightMeasureSpec, 0));
+ final int measuredWidth = resolveSizeAndState(dw, widthMeasureSpec, 0);
+ final int measuredHeight = resolveSizeAndState(dh, heightMeasureSpec, 0);
+ setMeasuredDimension(measuredWidth, measuredHeight);
}
@Override
@@ -1702,7 +1719,7 @@
}
private void updateDrawableState() {
- int[] state = getDrawableState();
+ final int[] state = getDrawableState();
if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
mProgressDrawable.setState(state);
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 4b061d3..dc4d932 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -43,7 +43,6 @@
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -63,12 +62,6 @@
public class RadialTimePickerView extends View {
private static final String TAG = "RadialTimePickerView";
- private static final boolean DEBUG = false;
-
- private static final int DEBUG_COLOR = 0x20FF0000;
- private static final int DEBUG_TEXT_COLOR = 0x60FF0000;
- private static final int DEBUG_STROKE_WIDTH = 2;
-
private static final int HOURS = 0;
private static final int MINUTES = 1;
private static final int HOURS_INNER = 2;
@@ -93,8 +86,6 @@
private static final int[] HOURS_NUMBERS_24 = {0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
private static final int[] MINUTES_NUMBERS = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
- private static final int CENTER_RADIUS = 2;
-
private static final int FADE_OUT_DURATION = 500;
private static final int FADE_IN_DURATION = 500;
@@ -135,11 +126,12 @@
private final IntHolder[][] mAlphaSelector = new IntHolder[2][3];
private final Paint mPaintBackground = new Paint();
- private final Paint mPaintDebug = new Paint();
private final Typeface mTypeface;
- private final float[] mTextSize = new float[2];
+ private final ColorStateList[] mTextColor = new ColorStateList[3];
+ private final int[] mTextSize = new int[3];
+ private final int[] mTextInset = new int[3];
private final float[][] mOuterTextX = new float[2][12];
private final float[][] mOuterTextY = new float[2][12];
@@ -147,22 +139,14 @@
private final float[] mInnerTextX = new float[12];
private final float[] mInnerTextY = new float[12];
- private final float[] mNumbersRadiusMultiplier = new float[3];
-
- private final float[] mTextSizeMultiplier = new float[3];
-
private final int[] mLineLength = new int[3];
- private final int[] mSelectionRadius = new int[3];
- private final float mSelectionRadiusMultiplier;
private final int[] mSelectionDegrees = new int[3];
- private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<Animator>();
- private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<Animator>();
+ private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<>();
+ private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<>();
private final RadialPickerTouchHelper mTouchHelper;
- private ColorStateList mNumbersTextColor;
-
private boolean mIs24HourMode;
private boolean mShowHours;
@@ -172,9 +156,13 @@
*/
private boolean mIsOnInnerCircle;
- private float mXCenter;
- private float mYCenter;
- private float mCircleRadius;
+ private int mSelectorRadius;
+ private int mSelectorDotRadius;
+ private int mCenterDotRadius;
+
+ private int mXCenter;
+ private int mYCenter;
+ private int mCircleRadius;
private int mMinHypotenuseForInnerNumber;
private int mMaxHypotenuseForOuterNumber;
@@ -186,7 +174,8 @@
private AnimatorSet mTransition;
private int mAmOrPm;
- private int mDisabledAlpha;
+
+ private float mDisabledAlpha;
private OnValueSelectedListener mListener;
@@ -313,7 +302,7 @@
// Pull disabled alpha from theme.
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
- mDisabledAlpha = (int) (outValue.getFloat() * 255 + 0.5f);
+ mDisabledAlpha = outValue.getFloat();
// process style attributes
final Resources res = getResources();
@@ -332,8 +321,9 @@
}
}
- mNumbersTextColor = a.getColorStateList(
- R.styleable.TimePicker_numbersTextColor);
+ mTextColor[HOURS] = a.getColorStateList(R.styleable.TimePicker_numbersTextColor);
+ mTextColor[HOURS_INNER] = a.getColorStateList(R.styleable.TimePicker_numbersInnerTextColor);
+ mTextColor[MINUTES] = mTextColor[HOURS];
mPaint[HOURS] = new Paint();
mPaint[HOURS].setAntiAlias(true);
@@ -351,8 +341,8 @@
mPaintCenter.setColor(selectorActivatedColor);
mPaintCenter.setAntiAlias(true);
- final int textActivatedColor = mNumbersTextColor.getColorForState(
- StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0);
+ final int[] activatedStateSet = StateSet.get(
+ StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED);
mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint();
mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true);
@@ -360,7 +350,8 @@
mPaintSelector[HOURS][SELECTOR_DOT] = new Paint();
mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true);
- mColorSelector[HOURS][SELECTOR_DOT] = textActivatedColor;
+ mColorSelector[HOURS][SELECTOR_DOT] =
+ mTextColor[HOURS].getColorForState(activatedStateSet, 0);
mPaintSelector[HOURS][SELECTOR_LINE] = new Paint();
mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true);
@@ -373,7 +364,8 @@
mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint();
mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true);
- mColorSelector[MINUTES][SELECTOR_DOT] = textActivatedColor;
+ mColorSelector[MINUTES][SELECTOR_DOT] =
+ mTextColor[MINUTES].getColorForState(activatedStateSet, 0);
mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint();
mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true);
@@ -384,13 +376,17 @@
context.getColor(R.color.timepicker_default_numbers_background_color_material)));
mPaintBackground.setAntiAlias(true);
- if (DEBUG) {
- mPaintDebug.setColor(DEBUG_COLOR);
- mPaintDebug.setAntiAlias(true);
- mPaintDebug.setStrokeWidth(DEBUG_STROKE_WIDTH);
- mPaintDebug.setStyle(Paint.Style.STROKE);
- mPaintDebug.setTextAlign(Paint.Align.CENTER);
- }
+ mSelectorRadius = res.getDimensionPixelSize(R.dimen.timepicker_selector_radius);
+ mSelectorDotRadius = res.getDimensionPixelSize(R.dimen.timepicker_selector_dot_radius);
+ mCenterDotRadius = res.getDimensionPixelSize(R.dimen.timepicker_center_dot_radius);
+
+ mTextSize[HOURS] = res.getDimensionPixelSize(R.dimen.timepicker_text_size_normal);
+ mTextSize[MINUTES] = res.getDimensionPixelSize(R.dimen.timepicker_text_size_normal);
+ mTextSize[HOURS_INNER] = res.getDimensionPixelSize(R.dimen.timepicker_text_size_inner);
+
+ mTextInset[HOURS] = res.getDimensionPixelSize(R.dimen.timepicker_text_inset_normal);
+ mTextInset[MINUTES] = res.getDimensionPixelSize(R.dimen.timepicker_text_inset_normal);
+ mTextInset[HOURS_INNER] = res.getDimensionPixelSize(R.dimen.timepicker_text_inset_inner);
mShowHours = true;
mIs24HourMode = false;
@@ -407,8 +403,6 @@
initHoursAndMinutesText();
initData();
- mSelectionRadiusMultiplier = res.getFloat(R.dimen.timepicker_selection_radius_multiplier);
-
a.recycle();
// Initial values
@@ -621,30 +615,6 @@
mOuterTextMinutes = mMinutesTexts;
- final Resources res = getResources();
-
- if (mIs24HourMode) {
- mNumbersRadiusMultiplier[HOURS] = res.getFloat(
- R.dimen.timepicker_numbers_radius_multiplier_outer);
- mTextSizeMultiplier[HOURS] = res.getFloat(
- R.dimen.timepicker_text_size_multiplier_outer);
-
- mNumbersRadiusMultiplier[HOURS_INNER] = res.getFloat(
- R.dimen.timepicker_numbers_radius_multiplier_inner);
- mTextSizeMultiplier[HOURS_INNER] = res.getFloat(
- R.dimen.timepicker_text_size_multiplier_inner);
- } else {
- mNumbersRadiusMultiplier[HOURS] = res.getFloat(
- R.dimen.timepicker_numbers_radius_multiplier_normal);
- mTextSizeMultiplier[HOURS] = res.getFloat(
- R.dimen.timepicker_text_size_multiplier_normal);
- }
-
- mNumbersRadiusMultiplier[MINUTES] = res.getFloat(
- R.dimen.timepicker_numbers_radius_multiplier_normal);
- mTextSizeMultiplier[MINUTES] = res.getFloat(
- R.dimen.timepicker_text_size_multiplier_normal);
-
final int hoursAlpha = mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT;
mAlpha[HOURS].setValue(hoursAlpha);
mAlphaSelector[HOURS][SELECTOR_CIRCLE].setValue(hoursAlpha);
@@ -668,96 +638,78 @@
mYCenter = getHeight() / 2;
mCircleRadius = Math.min(mXCenter, mYCenter);
- mMinHypotenuseForInnerNumber = (int) (mCircleRadius
- * mNumbersRadiusMultiplier[HOURS_INNER]) - mSelectionRadius[HOURS];
- mMaxHypotenuseForOuterNumber = (int) (mCircleRadius
- * mNumbersRadiusMultiplier[HOURS]) + mSelectionRadius[HOURS];
- mHalfwayHypotenusePoint = (int) (mCircleRadius
- * ((mNumbersRadiusMultiplier[HOURS] + mNumbersRadiusMultiplier[HOURS_INNER]) / 2));
-
- mTextSize[HOURS] = mCircleRadius * mTextSizeMultiplier[HOURS];
- mTextSize[MINUTES] = mCircleRadius * mTextSizeMultiplier[MINUTES];
-
- if (mIs24HourMode) {
- mTextSize[HOURS_INNER] = mCircleRadius * mTextSizeMultiplier[HOURS_INNER];
- }
+ mMinHypotenuseForInnerNumber = mCircleRadius - mTextInset[HOURS_INNER] - mSelectorRadius;
+ mMaxHypotenuseForOuterNumber = mCircleRadius - mTextInset[HOURS] - mSelectorRadius;
+ mHalfwayHypotenusePoint = mCircleRadius - (mTextInset[HOURS] + mTextInset[HOURS_INNER]) / 2;
calculatePositionsHours();
calculatePositionsMinutes();
- mSelectionRadius[HOURS] = (int) (mCircleRadius * mSelectionRadiusMultiplier);
- mSelectionRadius[HOURS_INNER] = mSelectionRadius[HOURS];
- mSelectionRadius[MINUTES] = (int) (mCircleRadius * mSelectionRadiusMultiplier);
-
mTouchHelper.invalidateRoot();
}
@Override
public void onDraw(Canvas canvas) {
- if (!mInputEnabled) {
- canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), mDisabledAlpha);
- } else {
- canvas.save();
- }
+ final float alphaMod = mInputEnabled ? 1 : mDisabledAlpha;
drawCircleBackground(canvas);
-
- final int hoursAlpha = mAlpha[HOURS].getValue();
- if (hoursAlpha > 0) {
- // Draw the hour selector under the elements.
- drawSelector(canvas, mIsOnInnerCircle ? HOURS_INNER : HOURS, null);
-
- // Draw outer hours.
- drawTextElements(canvas, mTextSize[HOURS], mTypeface, mOuterTextHours,
- mOuterTextX[HOURS], mOuterTextY[HOURS], mPaint[HOURS], hoursAlpha,
- !mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
-
- // Draw inner hours (12-23) for 24-hour time.
- if (mIs24HourMode && mInnerTextHours != null) {
- drawTextElements(canvas, mTextSize[HOURS_INNER], mTypeface, mInnerTextHours,
- mInnerTextX, mInnerTextY, mPaint[HOURS], hoursAlpha,
- mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
- }
- }
-
- final int minutesAlpha = mAlpha[MINUTES].getValue();
- if (minutesAlpha > 0) {
- drawSelector(canvas, MINUTES, mSelectorPath);
-
- // Exclude the selector region, then draw minutes with no
- // activated states.
- canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipPath(mSelectorPath, Region.Op.DIFFERENCE);
- drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mOuterTextMinutes,
- mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES], minutesAlpha,
- false, 0, false);
- canvas.restore();
-
- // Intersect the selector region, then draw minutes with only
- // activated states.
- canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipPath(mSelectorPath, Region.Op.INTERSECT);
- drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mOuterTextMinutes,
- mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES], minutesAlpha,
- true, mSelectionDegrees[MINUTES], true);
- canvas.restore();
- }
-
- drawCenter(canvas);
-
- if (DEBUG) {
- drawDebug(canvas);
- }
-
- canvas.restore();
+ drawHours(canvas, alphaMod);
+ drawMinutes(canvas, alphaMod);
+ drawCenter(canvas, alphaMod);
}
private void drawCircleBackground(Canvas canvas) {
canvas.drawCircle(mXCenter, mYCenter, mCircleRadius, mPaintBackground);
}
- private void drawCenter(Canvas canvas) {
- canvas.drawCircle(mXCenter, mYCenter, CENTER_RADIUS, mPaintCenter);
+ private void drawHours(Canvas canvas, float alphaMod) {
+ final int hoursAlpha = (int) (mAlpha[HOURS].getValue() * alphaMod + 0.5f);
+ if (hoursAlpha > 0) {
+ // Draw the hour selector under the elements.
+ drawSelector(canvas, mIsOnInnerCircle ? HOURS_INNER : HOURS, null, alphaMod);
+
+ // Draw outer hours.
+ drawTextElements(canvas, mTextSize[HOURS], mTypeface, mTextColor[HOURS],
+ mOuterTextHours, mOuterTextX[HOURS], mOuterTextY[HOURS], mPaint[HOURS],
+ hoursAlpha, !mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
+
+ // Draw inner hours (12-23) for 24-hour time.
+ if (mIs24HourMode && mInnerTextHours != null) {
+ drawTextElements(canvas, mTextSize[HOURS_INNER], mTypeface, mTextColor[HOURS_INNER],
+ mInnerTextHours, mInnerTextX, mInnerTextY, mPaint[HOURS], hoursAlpha,
+ mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
+ }
+ }
+ }
+
+ private void drawMinutes(Canvas canvas, float alphaMod) {
+ final int minutesAlpha = (int) (mAlpha[MINUTES].getValue() * alphaMod + 0.5f);
+ if (minutesAlpha > 0) {
+ drawSelector(canvas, MINUTES, mSelectorPath, alphaMod);
+
+ // Exclude the selector region, then draw minutes with no
+ // activated states.
+ canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipPath(mSelectorPath, Region.Op.DIFFERENCE);
+ drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
+ mOuterTextMinutes, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
+ minutesAlpha, false, 0, false);
+ canvas.restore();
+
+ // Intersect the selector region, then draw minutes with only
+ // activated states.
+ canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipPath(mSelectorPath, Region.Op.INTERSECT);
+ drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
+ mOuterTextMinutes, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
+ minutesAlpha, true, mSelectionDegrees[MINUTES], true);
+ canvas.restore();
+ }
+ }
+
+ private void drawCenter(Canvas canvas, float alphaMod) {
+ mPaintCenter.setAlpha((int) (255 * alphaMod + 0.5f));
+ canvas.drawCircle(mXCenter, mYCenter, mCenterDotRadius, mPaintCenter);
}
private int getMultipliedAlpha(int argb, int alpha) {
@@ -766,9 +718,9 @@
private final Path mSelectorPath = new Path();
- private void drawSelector(Canvas canvas, int index, Path selectorPath) {
+ private void drawSelector(Canvas canvas, int index, Path selectorPath, float alphaMod) {
// Calculate the current radius at which to place the selection circle.
- mLineLength[index] = (int) (mCircleRadius * mNumbersRadiusMultiplier[index]);
+ mLineLength[index] = mCircleRadius - mTextInset[index];
final double selectionRadians = Math.toRadians(mSelectionDegrees[index]);
@@ -781,16 +733,16 @@
// Draw the selection circle
color = mColorSelector[index % 2][SELECTOR_CIRCLE];
- alpha = mAlphaSelector[index % 2][SELECTOR_CIRCLE].getValue();
+ alpha = (int) (mAlphaSelector[index % 2][SELECTOR_CIRCLE].getValue() * alphaMod + 0.5f);
paint = mPaintSelector[index % 2][SELECTOR_CIRCLE];
paint.setColor(color);
paint.setAlpha(getMultipliedAlpha(color, alpha));
- canvas.drawCircle(pointX, pointY, mSelectionRadius[index], paint);
+ canvas.drawCircle(pointX, pointY, mSelectorRadius, paint);
// If needed, set up the clip path for later.
if (selectorPath != null) {
mSelectorPath.reset();
- mSelectorPath.addCircle(pointX, pointY, mSelectionRadius[index], Path.Direction.CCW);
+ mSelectorPath.addCircle(pointX, pointY, mSelectorRadius, Path.Direction.CCW);
}
// Draw the dot if needed.
@@ -798,80 +750,35 @@
if (shouldDrawDot) {
// We're not on a direct tick
color = mColorSelector[index % 2][SELECTOR_DOT];
- alpha = mAlphaSelector[index % 2][SELECTOR_DOT].getValue();
+ alpha = (int) (mAlphaSelector[index % 2][SELECTOR_DOT].getValue() * alphaMod + 0.5f);
paint = mPaintSelector[index % 2][SELECTOR_DOT];
paint.setColor(color);
paint.setAlpha(getMultipliedAlpha(color, alpha));
- canvas.drawCircle(pointX, pointY, (mSelectionRadius[index] * 0.125f), paint);
+ canvas.drawCircle(pointX, pointY, mSelectorDotRadius, paint);
}
- // Shorten the line to only go to the edge of the selection circle.
- final int lineLength = mLineLength[index] - mSelectionRadius[index];
- pointX = mXCenter + (int) (lineLength * Math.sin(selectionRadians));
- pointY = mYCenter - (int) (lineLength * Math.cos(selectionRadians));
+ // Shorten the line to only go from the edge of the center dot to the
+ // edge of the selection circle.
+ final double sin = Math.sin(selectionRadians);
+ final double cos = Math.cos(selectionRadians);
+ final int lineLength = mLineLength[index] - mSelectorRadius;
+ final int centerX = mXCenter + (int) (mCenterDotRadius * sin);
+ final int centerY = mYCenter - (int) (mCenterDotRadius * cos);
+ pointX = centerX + (int) (lineLength * sin);
+ pointY = centerY - (int) (lineLength * cos);
// Draw the line
color = mColorSelector[index % 2][SELECTOR_LINE];
- alpha = mAlphaSelector[index % 2][SELECTOR_LINE].getValue();
+ alpha = (int) (mAlphaSelector[index % 2][SELECTOR_LINE].getValue() * alphaMod + 0.5f);
paint = mPaintSelector[index % 2][SELECTOR_LINE];
paint.setColor(color);
paint.setAlpha(getMultipliedAlpha(color, alpha));
canvas.drawLine(mXCenter, mYCenter, pointX, pointY, paint);
}
- private void drawDebug(Canvas canvas) {
- // Draw outer numbers circle
- final float outerRadius = mCircleRadius * mNumbersRadiusMultiplier[HOURS];
- canvas.drawCircle(mXCenter, mYCenter, outerRadius, mPaintDebug);
-
- // Draw inner numbers circle
- final float innerRadius = mCircleRadius * mNumbersRadiusMultiplier[HOURS_INNER];
- canvas.drawCircle(mXCenter, mYCenter, innerRadius, mPaintDebug);
-
- // Draw outer background circle
- canvas.drawCircle(mXCenter, mYCenter, mCircleRadius, mPaintDebug);
-
- // Draw outer rectangle for circles
- float left = mXCenter - outerRadius;
- float top = mYCenter - outerRadius;
- float right = mXCenter + outerRadius;
- float bottom = mYCenter + outerRadius;
- canvas.drawRect(left, top, right, bottom, mPaintDebug);
-
- // Draw outer rectangle for background
- left = mXCenter - mCircleRadius;
- top = mYCenter - mCircleRadius;
- right = mXCenter + mCircleRadius;
- bottom = mYCenter + mCircleRadius;
- canvas.drawRect(left, top, right, bottom, mPaintDebug);
-
- // Draw outer view rectangle
- canvas.drawRect(0, 0, getWidth(), getHeight(), mPaintDebug);
-
- // Draw selected time
- final String selected = String.format("%02d:%02d", getCurrentHour(), getCurrentMinute());
-
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- TextView tv = new TextView(getContext());
- tv.setLayoutParams(lp);
- tv.setText(selected);
- tv.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- Paint paint = tv.getPaint();
- paint.setColor(DEBUG_TEXT_COLOR);
-
- final int width = tv.getMeasuredWidth();
-
- float height = paint.descent() - paint.ascent();
- float x = mXCenter - width / 2;
- float y = mYCenter + 1.5f * height;
-
- canvas.drawText(selected, x, y, paint);
- }
-
private void calculatePositionsHours() {
// Calculate the text positions
- final float numbersRadius = mCircleRadius * mNumbersRadiusMultiplier[HOURS];
+ final float numbersRadius = mCircleRadius - mTextInset[HOURS];
// Calculate the positions for the 12 numbers in the main circle.
calculatePositions(mPaint[HOURS], numbersRadius, mXCenter, mYCenter,
@@ -879,9 +786,7 @@
// If we have an inner circle, calculate those positions too.
if (mIs24HourMode) {
- final float innerNumbersRadius = mCircleRadius
- * mNumbersRadiusMultiplier[HOURS_INNER];
-
+ final int innerNumbersRadius = mCircleRadius - mTextInset[HOURS_INNER];
calculatePositions(mPaint[HOURS], innerNumbersRadius, mXCenter, mYCenter,
mTextSize[HOURS_INNER], mInnerTextX, mInnerTextY);
}
@@ -889,7 +794,7 @@
private void calculatePositionsMinutes() {
// Calculate the text positions
- final float numbersRadius = mCircleRadius * mNumbersRadiusMultiplier[MINUTES];
+ final float numbersRadius = mCircleRadius - mTextInset[MINUTES];
// Calculate the positions for the 12 numbers in the main circle.
calculatePositions(mPaint[MINUTES], numbersRadius, mXCenter, mYCenter,
@@ -916,9 +821,9 @@
/**
* Draw the 12 text values at the positions specified by the textGrid parameters.
*/
- private void drawTextElements(Canvas canvas, float textSize, Typeface typeface, String[] texts,
- float[] textX, float[] textY, Paint paint, int alpha, boolean showActivated,
- int activatedDegrees, boolean activatedOnly) {
+ private void drawTextElements(Canvas canvas, float textSize, Typeface typeface,
+ ColorStateList textColor, String[] texts, float[] textX, float[] textY, Paint paint,
+ int alpha, boolean showActivated, int activatedDegrees, boolean activatedOnly) {
paint.setTextSize(textSize);
paint.setTypeface(typeface);
@@ -935,7 +840,7 @@
final int stateMask = StateSet.VIEW_STATE_ENABLED
| (showActivated && activated ? StateSet.VIEW_STATE_ACTIVATED : 0);
- final int color = mNumbersTextColor.getColorForState(StateSet.get(stateMask), 0);
+ final int color = textColor.getColorForState(StateSet.get(stateMask), 0);
paint.setColor(color);
paint.setAlpha(getMultipliedAlpha(color, alpha));
@@ -1058,10 +963,9 @@
}
} else {
final int index = (mShowHours) ? HOURS : MINUTES;
- final float length = (mCircleRadius * mNumbersRadiusMultiplier[index]);
+ final float length = (mCircleRadius - mTextInset[index]);
final int distanceToNumber = (int) (hypotenuse - length);
- final int maxAllowedDistance =
- (int) (mCircleRadius * (1 - mNumbersRadiusMultiplier[index]));
+ final int maxAllowedDistance = mTextInset[index];
if (distanceToNumber < -maxAllowedDistance
|| (constrainOutside && distanceToNumber > maxAllowedDistance)) {
return -1;
@@ -1431,18 +1335,18 @@
if (type == TYPE_HOUR) {
final boolean innerCircle = mIs24HourMode && value > 0 && value <= 12;
if (innerCircle) {
- centerRadius = mCircleRadius * mNumbersRadiusMultiplier[HOURS_INNER];
- radius = mSelectionRadius[HOURS_INNER];
+ centerRadius = mCircleRadius - mTextInset[HOURS_INNER];
+ radius = mSelectorRadius;
} else {
- centerRadius = mCircleRadius * mNumbersRadiusMultiplier[HOURS];
- radius = mSelectionRadius[HOURS];
+ centerRadius = mCircleRadius - mTextInset[HOURS];
+ radius = mSelectorRadius;
}
degrees = getDegreesForHour(value);
} else if (type == TYPE_MINUTE) {
- centerRadius = mCircleRadius * mNumbersRadiusMultiplier[MINUTES];
+ centerRadius = mCircleRadius - mTextInset[MINUTES];
degrees = getDegreesForMinute(value);
- radius = mSelectionRadius[MINUTES];
+ radius = mSelectorRadius;
} else {
// This should never happen.
centerRadius = 0;
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index f04bb3d..6586d11 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.IdRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
@@ -151,7 +152,7 @@
* @see #getCheckedRadioButtonId()
* @see #clearCheck()
*/
- public void check(int id) {
+ public void check(@IdRes int id) {
// don't even bother
if (id != -1 && (id == mCheckedId)) {
return;
@@ -168,7 +169,7 @@
setCheckedId(id);
}
- private void setCheckedId(int id) {
+ private void setCheckedId(@IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
@@ -193,6 +194,7 @@
*
* @attr ref android.R.styleable#RadioGroup_checkedButton
*/
+ @IdRes
public int getCheckedRadioButtonId() {
return mCheckedId;
}
@@ -331,7 +333,7 @@
* @param group the group in which the checked radio button has changed
* @param checkedId the unique identifier of the newly checked radio button
*/
- public void onCheckedChanged(RadioGroup group, int checkedId);
+ public void onCheckedChanged(RadioGroup group, @IdRes int checkedId);
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 89b1d54..fef56b8 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -617,15 +617,17 @@
}
}
- // Use the bottom-most view as the baseline.
+ // Use the bottom-most laid out view as the baseline.
View baselineView = null;
int baseline = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
- final int childBaseline = child.getBaseline();
- if (childBaseline >= baseline) {
- baselineView = child;
- baseline = childBaseline;
+ if (child.getVisibility() != GONE) {
+ final int childBaseline = child.getBaseline();
+ if (childBaseline >= baseline) {
+ baselineView = child;
+ baseline = childBaseline;
+ }
}
}
mBaselineView = baselineView;
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 6ee2b4c..f0bc303 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.annotation.Widget;
import android.app.AlertDialog;
@@ -46,7 +47,6 @@
import android.widget.ListPopupWindow.ForwardingListener;
import android.widget.PopupWindow.OnDismissListener;
-
/**
* A view that displays one child at a time and lets the user pick among them.
* The items in the Spinner come from the {@link Adapter} associated with
@@ -331,7 +331,7 @@
*
* @attr ref android.R.styleable#Spinner_popupBackground
*/
- public void setPopupBackgroundResource(int resId) {
+ public void setPopupBackgroundResource(@DrawableRes int resId) {
setPopupBackgroundDrawable(getPopupContext().getDrawable(resId));
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index b959ddc..ce1834e 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -17,7 +17,9 @@
package android.widget;
import android.animation.ObjectAnimator;
+import android.annotation.DrawableRes;
import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -263,7 +265,7 @@
*
* @attr ref android.R.styleable#Switch_switchTextAppearance
*/
- public void setSwitchTextAppearance(Context context, int resid) {
+ public void setSwitchTextAppearance(Context context, @StyleRes int resid) {
TypedArray appearance =
context.obtainStyledAttributes(resid,
com.android.internal.R.styleable.TextAppearance);
@@ -471,7 +473,7 @@
*
* @attr ref android.R.styleable#Switch_track
*/
- public void setTrackResource(int resId) {
+ public void setTrackResource(@DrawableRes int resId) {
setTrackDrawable(getContext().getDrawable(resId));
}
@@ -593,7 +595,7 @@
*
* @attr ref android.R.styleable#Switch_thumb
*/
- public void setThumbResource(int resId) {
+ public void setThumbResource(@DrawableRes int resId) {
setThumbDrawable(getContext().getDrawable(resId));
}
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 88ecb13..f90a0a7 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -17,6 +17,7 @@
package android.widget;
import android.R;
+import android.annotation.DrawableRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -244,7 +245,7 @@
* @param resId the resource identifier of the drawable to use as a
* divider.
*/
- public void setDividerDrawable(int resId) {
+ public void setDividerDrawable(@DrawableRes int resId) {
setDividerDrawable(mContext.getDrawable(resId));
}
@@ -265,7 +266,7 @@
* @param resId the resource identifier of the drawable to use as the
* left strip drawable
*/
- public void setLeftStripDrawable(int resId) {
+ public void setLeftStripDrawable(@DrawableRes int resId) {
setLeftStripDrawable(mContext.getDrawable(resId));
}
@@ -286,7 +287,7 @@
* @param resId the resource identifier of the drawable to use as the
* right strip drawable
*/
- public void setRightStripDrawable(int resId) {
+ public void setRightStripDrawable(@DrawableRes int resId) {
setRightStripDrawable(mContext.getDrawable(resId));
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 848c1c0..2d0a9cb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,8 +17,12 @@
package android.widget;
import android.R;
+import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.StyleRes;
+import android.annotation.XmlRes;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -43,6 +47,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ParcelableParcel;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1608,7 +1613,8 @@
* @hide
*/
public final UndoManager getUndoManager() {
- return mEditor == null ? null : mEditor.mUndoManager;
+ // TODO: Consider supporting a global undo manager.
+ throw new UnsupportedOperationException("not implemented");
}
/**
@@ -1626,22 +1632,12 @@
* @hide
*/
public final void setUndoManager(UndoManager undoManager, String tag) {
- if (undoManager != null) {
- createEditorIfNeeded();
- mEditor.mUndoManager = undoManager;
- mEditor.mUndoOwner = undoManager.getOwner(tag, this);
- mEditor.mUndoInputFilter = new Editor.UndoInputFilter(mEditor);
- if (!(mText instanceof Editable)) {
- setText(mText, BufferType.EDITABLE);
- }
-
- setFilters((Editable) mText, mFilters);
- } else if (mEditor != null) {
- // XXX need to destroy all associated state.
- mEditor.mUndoManager = null;
- mEditor.mUndoOwner = null;
- mEditor.mUndoInputFilter = null;
- }
+ // TODO: Consider supporting a global undo manager. An implementation will need to:
+ // * createEditorIfNeeded()
+ // * Promote to BufferType.EDITABLE if needed.
+ // * Update the UndoManager and UndoOwner.
+ // Likewise it will need to be able to restore the default UndoManager.
+ throw new UnsupportedOperationException("not implemented");
}
/**
@@ -2173,7 +2169,8 @@
* @attr ref android.R.styleable#TextView_drawableBottom
*/
@android.view.RemotableViewMethod
- public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
+ public void setCompoundDrawablesWithIntrinsicBounds(@DrawableRes int left,
+ @DrawableRes int top, @DrawableRes int right, @DrawableRes int bottom) {
final Context context = getContext();
setCompoundDrawablesWithIntrinsicBounds(left != 0 ? context.getDrawable(left) : null,
top != 0 ? context.getDrawable(top) : null,
@@ -2374,8 +2371,8 @@
* @attr ref android.R.styleable#TextView_drawableBottom
*/
@android.view.RemotableViewMethod
- public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
- int bottom) {
+ public void setCompoundDrawablesRelativeWithIntrinsicBounds(@DrawableRes int start,
+ @DrawableRes int top, @DrawableRes int end, @DrawableRes int bottom) {
final Context context = getContext();
setCompoundDrawablesRelativeWithIntrinsicBounds(
start != 0 ? context.getDrawable(start) : null,
@@ -2643,7 +2640,7 @@
* Sets the text color, size, style, hint color, and highlight color
* from the specified TextAppearance resource.
*/
- public void setTextAppearance(Context context, int resid) {
+ public void setTextAppearance(Context context, @StyleRes int resid) {
TypedArray appearance =
context.obtainStyledAttributes(resid,
com.android.internal.R.styleable.TextAppearance);
@@ -3894,6 +3891,9 @@
ss.error = getError();
+ if (mEditor != null) {
+ ss.editorState = mEditor.saveInstanceState();
+ }
return ss;
}
@@ -3963,6 +3963,11 @@
}
});
}
+
+ if (ss.editorState != null) {
+ createEditorIfNeeded();
+ mEditor.restoreInstanceState(ss.editorState);
+ }
}
/**
@@ -4267,11 +4272,11 @@
}
@android.view.RemotableViewMethod
- public final void setText(int resid) {
+ public final void setText(@StringRes int resid) {
setText(getContext().getResources().getText(resid));
}
- public final void setText(int resid, BufferType type) {
+ public final void setText(@StringRes int resid, BufferType type) {
setText(getContext().getResources().getText(resid), type);
}
@@ -4307,7 +4312,7 @@
* @attr ref android.R.styleable#TextView_hint
*/
@android.view.RemotableViewMethod
- public final void setHint(int resid) {
+ public final void setHint(@StringRes int resid) {
setHint(getContext().getResources().getText(resid));
}
@@ -4711,7 +4716,7 @@
* @see EditorInfo#extras
* @attr ref android.R.styleable#TextView_editorExtras
*/
- public void setInputExtras(int xmlResId) throws XmlPullParserException, IOException {
+ public void setInputExtras(@XmlRes int xmlResId) throws XmlPullParserException, IOException {
createEditorIfNeeded();
XmlResourceParser parser = getResources().getXml(xmlResId);
mEditor.createInputContentTypeIfNeeded();
@@ -8370,14 +8375,19 @@
@Override
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
- final int filteredMetaState = event.getMetaState() & ~KeyEvent.META_CTRL_MASK;
- if (KeyEvent.metaStateHasNoModifiers(filteredMetaState)) {
+ if (event.hasModifiers(KeyEvent.META_CTRL_ON)) {
+ // Handle Ctrl-only shortcuts.
switch (keyCode) {
case KeyEvent.KEYCODE_A:
if (canSelectText()) {
return onTextContextMenuItem(ID_SELECT_ALL);
}
break;
+ case KeyEvent.KEYCODE_Z:
+ if (canUndo()) {
+ return onTextContextMenuItem(ID_UNDO);
+ }
+ break;
case KeyEvent.KEYCODE_X:
if (canCut()) {
return onTextContextMenuItem(ID_CUT);
@@ -8394,6 +8404,19 @@
}
break;
}
+ } else if (event.hasModifiers(KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)) {
+ // Handle Ctrl-Shift shortcuts.
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_Z:
+ if (canRedo()) {
+ return onTextContextMenuItem(ID_REDO);
+ }
+ break;
+ case KeyEvent.KEYCODE_V:
+ if (canPaste()) {
+ return onTextContextMenuItem(ID_PASTE_AS_PLAIN_TEXT);
+ }
+ }
}
return super.onKeyShortcut(keyCode, event);
}
@@ -8770,9 +8793,12 @@
}
static final int ID_SELECT_ALL = android.R.id.selectAll;
+ static final int ID_UNDO = android.R.id.undo;
+ static final int ID_REDO = android.R.id.redo;
static final int ID_CUT = android.R.id.cut;
static final int ID_COPY = android.R.id.copy;
static final int ID_PASTE = android.R.id.paste;
+ static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
/**
* Called when a context menu option for the text view is selected. Currently
@@ -8800,8 +8826,24 @@
selectAllText();
return true;
+ case ID_UNDO:
+ if (mEditor != null) {
+ mEditor.undo();
+ }
+ return true; // Returns true even if nothing was undone.
+
+ case ID_REDO:
+ if (mEditor != null) {
+ mEditor.redo();
+ }
+ return true; // Returns true even if nothing was undone.
+
case ID_PASTE:
- paste(min, max);
+ paste(min, max, true /* withFormatting */);
+ return true;
+
+ case ID_PASTE_AS_PLAIN_TEXT:
+ paste(min, max, false /* withFormatting */);
return true;
case ID_CUT:
@@ -8929,7 +8971,17 @@
* @hide
*/
protected void stopSelectionActionMode() {
- mEditor.stopSelectionActionMode();
+ if (mEditor != null) {
+ mEditor.stopSelectionActionMode();
+ }
+ }
+
+ boolean canUndo() {
+ return mEditor != null && mEditor.canUndo();
+ }
+
+ boolean canRedo() {
+ return mEditor != null && mEditor.canRedo();
}
boolean canCut() {
@@ -8975,14 +9027,21 @@
/**
* Paste clipboard content between min and max positions.
*/
- private void paste(int min, int max) {
+ private void paste(int min, int max, boolean withFormatting) {
ClipboardManager clipboard =
(ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip != null) {
boolean didFirst = false;
for (int i=0; i<clip.getItemCount(); i++) {
- CharSequence paste = clip.getItemAt(i).coerceToStyledText(getContext());
+ final CharSequence paste;
+ if (withFormatting) {
+ paste = clip.getItemAt(i).coerceToStyledText(getContext());
+ } else {
+ // Get an item as text and remove all spans by toString().
+ final CharSequence text = clip.getItemAt(i).coerceToText(getContext());
+ paste = (text instanceof Spanned) ? text.toString() : text;
+ }
if (paste != null) {
if (!didFirst) {
Selection.setSelection((Spannable) mText, max);
@@ -9299,6 +9358,7 @@
CharSequence text;
boolean frozenWithFocus;
CharSequence error;
+ ParcelableParcel editorState; // Optional state from Editor.
SavedState(Parcelable superState) {
super(superState);
@@ -9318,6 +9378,13 @@
out.writeInt(1);
TextUtils.writeToParcel(error, out, flags);
}
+
+ if (editorState == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ editorState.writeToParcel(out, flags);
+ }
}
@Override
@@ -9353,6 +9420,10 @@
if (in.readInt() != 0) {
error = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
}
+
+ if (in.readInt() != 0) {
+ editorState = ParcelableParcel.CREATOR.createFromParcel(in);
+ }
}
}
@@ -9650,4 +9721,4 @@
TextView.this.spanChange(buf, what, s, -1, e, -1);
}
}
-}
+}
\ No newline at end of file
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 05c7a5f..ed052af 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -91,6 +91,7 @@
private int mInitialHourOfDay;
private int mInitialMinute;
private boolean mIs24HourView;
+ private boolean mIsAmPmAtStart;
// For hardware IME input.
private char mPlaceholderText;
@@ -284,24 +285,37 @@
}
private void updateHeaderAmPm() {
+
if (mIs24HourView) {
mAmPmLayout.setVisibility(View.GONE);
} else {
// Ensure that AM/PM layout is in the correct position.
final String dateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale, "hm");
- final boolean amPmAtStart = dateTimePattern.startsWith("a");
- final ViewGroup parent = (ViewGroup) mAmPmLayout.getParent();
- final int targetIndex = amPmAtStart ? 0 : parent.getChildCount() - 1;
- final int currentIndex = parent.indexOfChild(mAmPmLayout);
- if (targetIndex != currentIndex) {
- parent.removeView(mAmPmLayout);
- parent.addView(mAmPmLayout, targetIndex);
- }
+ final boolean isAmPmAtStart = dateTimePattern.startsWith("a");
+ setAmPmAtStart(isAmPmAtStart);
updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
}
}
+ private void setAmPmAtStart(boolean isAmPmAtStart) {
+ if (mIsAmPmAtStart != isAmPmAtStart) {
+ mIsAmPmAtStart = isAmPmAtStart;
+
+ final RelativeLayout.LayoutParams params =
+ (RelativeLayout.LayoutParams) mAmPmLayout.getLayoutParams();
+ if (isAmPmAtStart) {
+ params.removeRule(RelativeLayout.RIGHT_OF);
+ params.addRule(RelativeLayout.LEFT_OF, mHourView.getId());
+ } else {
+ params.removeRule(RelativeLayout.LEFT_OF);
+ params.addRule(RelativeLayout.RIGHT_OF, mMinuteView.getId());
+ }
+
+ mAmPmLayout.setLayoutParams(params);
+ }
+ }
+
/**
* Set the current hour.
*/
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index be4cdc1..207f675 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -17,6 +17,7 @@
package android.widget;
import android.annotation.IntDef;
+import android.annotation.StringRes;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.content.Context;
@@ -280,7 +281,7 @@
*
* @throws Resources.NotFoundException if the resource can't be found.
*/
- public static Toast makeText(Context context, int resId, @Duration int duration)
+ public static Toast makeText(Context context, @StringRes int resId, @Duration int duration)
throws Resources.NotFoundException {
return makeText(context, context.getResources().getText(resId), duration);
}
@@ -289,7 +290,7 @@
* Update the text in a Toast that was previously created using one of the makeText() methods.
* @param resId The new text for the Toast.
*/
- public void setText(int resId) {
+ public void setText(@StringRes int resId) {
setText(mContext.getText(resId));
}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 5a10524..6d90420 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -26,7 +26,7 @@
import android.service.voice.IVoiceInteractionSession;
interface IVoiceInteractionManagerService {
- void startSession(IVoiceInteractionService service, in Bundle sessionArgs);
+ void startSession(IVoiceInteractionService service, in Bundle sessionArgs, int flags);
boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
IVoiceInteractor interactor);
int startVoiceActivity(IBinder token, in Intent intent, String resolvedType);
diff --git a/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java b/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java
deleted file mode 100644
index faaac7f..0000000
--- a/core/java/com/android/internal/http/multipart/ByteArrayPartSource.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/ByteArrayPartSource.java,v 1.7 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-
-/**
- * A PartSource that reads from a byte array. This class should be used when
- * the data to post is already loaded into memory.
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- *
- * @since 2.0
- */
-public class ByteArrayPartSource implements PartSource {
-
- /** Name of the source file. */
- private String fileName;
-
- /** Byte array of the source file. */
- private byte[] bytes;
-
- /**
- * Constructor for ByteArrayPartSource.
- *
- * @param fileName the name of the file these bytes represent
- * @param bytes the content of this part
- */
- public ByteArrayPartSource(String fileName, byte[] bytes) {
-
- this.fileName = fileName;
- this.bytes = bytes;
-
- }
-
- /**
- * @see PartSource#getLength()
- */
- public long getLength() {
- return bytes.length;
- }
-
- /**
- * @see PartSource#getFileName()
- */
- public String getFileName() {
- return fileName;
- }
-
- /**
- * @see PartSource#createInputStream()
- */
- public InputStream createInputStream() {
- return new ByteArrayInputStream(bytes);
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/FilePart.java b/core/java/com/android/internal/http/multipart/FilePart.java
deleted file mode 100644
index 45e4be6..0000000
--- a/core/java/com/android/internal/http/multipart/FilePart.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePart.java,v 1.19 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * This class implements a part of a Multipart post object that
- * consists of a file.
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead.
- * The Apache HTTP client is no longer maintained and may be removed in a future
- * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
- * for further details.
- */
-@Deprecated
-public class FilePart extends PartBase {
-
- /** Default content encoding of file attachments. */
- public static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
-
- /** Default charset of file attachments. */
- public static final String DEFAULT_CHARSET = "ISO-8859-1";
-
- /** Default transfer encoding of file attachments. */
- public static final String DEFAULT_TRANSFER_ENCODING = "binary";
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(FilePart.class);
-
- /** Attachment's file name */
- protected static final String FILE_NAME = "; filename=";
-
- /** Attachment's file name as a byte array */
- private static final byte[] FILE_NAME_BYTES =
- EncodingUtils.getAsciiBytes(FILE_NAME);
-
- /** Source of the file part. */
- private PartSource source;
-
- /**
- * FilePart Constructor.
- *
- * @param name the name for this part
- * @param partSource the source for this part
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- */
- public FilePart(String name, PartSource partSource, String contentType, String charset) {
-
- super(
- name,
- contentType == null ? DEFAULT_CONTENT_TYPE : contentType,
- charset == null ? "ISO-8859-1" : charset,
- DEFAULT_TRANSFER_ENCODING
- );
-
- if (partSource == null) {
- throw new IllegalArgumentException("Source may not be null");
- }
- this.source = partSource;
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name for this part
- * @param partSource the source for this part
- */
- public FilePart(String name, PartSource partSource) {
- this(name, partSource, null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param file the file to post
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, File file)
- throws FileNotFoundException {
- this(name, new FilePartSource(file), null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param file the file to post
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, File file, String contentType, String charset)
- throws FileNotFoundException {
- this(name, new FilePartSource(file), contentType, charset);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param fileName the file name
- * @param file the file to post
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, String fileName, File file)
- throws FileNotFoundException {
- this(name, new FilePartSource(fileName, file), null, null);
- }
-
- /**
- * FilePart Constructor.
- *
- * @param name the name of the file part
- * @param fileName the file name
- * @param file the file to post
- * @param contentType the content type for this part, if <code>null</code> the
- * {@link #DEFAULT_CONTENT_TYPE default} is used
- * @param charset the charset encoding for this part, if <code>null</code> the
- * {@link #DEFAULT_CHARSET default} is used
- *
- * @throws FileNotFoundException if the <i>file</i> is not a normal
- * file or if it is not readable.
- */
- public FilePart(String name, String fileName, File file, String contentType, String charset)
- throws FileNotFoundException {
- this(name, new FilePartSource(fileName, file), contentType, charset);
- }
-
- /**
- * Write the disposition header to the output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs
- * @see Part#sendDispositionHeader(OutputStream)
- */
- @Override
- protected void sendDispositionHeader(OutputStream out)
- throws IOException {
- LOG.trace("enter sendDispositionHeader(OutputStream out)");
- super.sendDispositionHeader(out);
- String filename = this.source.getFileName();
- if (filename != null) {
- out.write(FILE_NAME_BYTES);
- out.write(QUOTE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(filename));
- out.write(QUOTE_BYTES);
- }
- }
-
- /**
- * Write the data in "source" to the specified stream.
- * @param out The output stream.
- * @throws IOException if an IO problem occurs.
- * @see Part#sendData(OutputStream)
- */
- @Override
- protected void sendData(OutputStream out) throws IOException {
- LOG.trace("enter sendData(OutputStream out)");
- if (lengthOfData() == 0) {
-
- // this file contains no data, so there is nothing to send.
- // we don't want to create a zero length buffer as this will
- // cause an infinite loop when reading.
- LOG.debug("No data to send.");
- return;
- }
-
- byte[] tmp = new byte[4096];
- InputStream instream = source.createInputStream();
- try {
- int len;
- while ((len = instream.read(tmp)) >= 0) {
- out.write(tmp, 0, len);
- }
- } finally {
- // we're done with the stream, close it
- instream.close();
- }
- }
-
- /**
- * Returns the source of the file part.
- *
- * @return The source.
- */
- protected PartSource getSource() {
- LOG.trace("enter getSource()");
- return this.source;
- }
-
- /**
- * Return the length of the data.
- * @return The length.
- * @see Part#lengthOfData()
- */
- @Override
- protected long lengthOfData() {
- LOG.trace("enter lengthOfData()");
- return source.getLength();
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/FilePartSource.java b/core/java/com/android/internal/http/multipart/FilePartSource.java
deleted file mode 100644
index eb5cc0f..0000000
--- a/core/java/com/android/internal/http/multipart/FilePartSource.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/FilePartSource.java,v 1.10 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A PartSource that reads from a File.
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- * @author <a href="mailto:mdiggory@latte.harvard.edu">Mark Diggory</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- *
- * @since 2.0
- */
-public class FilePartSource implements PartSource {
-
- /** File part file. */
- private File file = null;
-
- /** File part file name. */
- private String fileName = null;
-
- /**
- * Constructor for FilePartSource.
- *
- * @param file the FilePart source File.
- *
- * @throws FileNotFoundException if the file does not exist or
- * cannot be read
- */
- public FilePartSource(File file) throws FileNotFoundException {
- this.file = file;
- if (file != null) {
- if (!file.isFile()) {
- throw new FileNotFoundException("File is not a normal file.");
- }
- if (!file.canRead()) {
- throw new FileNotFoundException("File is not readable.");
- }
- this.fileName = file.getName();
- }
- }
-
- /**
- * Constructor for FilePartSource.
- *
- * @param fileName the file name of the FilePart
- * @param file the source File for the FilePart
- *
- * @throws FileNotFoundException if the file does not exist or
- * cannot be read
- */
- public FilePartSource(String fileName, File file)
- throws FileNotFoundException {
- this(file);
- if (fileName != null) {
- this.fileName = fileName;
- }
- }
-
- /**
- * Return the length of the file
- * @return the length of the file.
- * @see PartSource#getLength()
- */
- public long getLength() {
- if (this.file != null) {
- return this.file.length();
- } else {
- return 0;
- }
- }
-
- /**
- * Return the current filename
- * @return the filename.
- * @see PartSource#getFileName()
- */
- public String getFileName() {
- return (fileName == null) ? "noname" : fileName;
- }
-
- /**
- * Return a new {@link FileInputStream} for the current filename.
- * @return the new input stream.
- * @throws IOException If an IO problem occurs.
- * @see PartSource#createInputStream()
- */
- public InputStream createInputStream() throws IOException {
- if (this.file != null) {
- return new FileInputStream(this.file);
- } else {
- return new ByteArrayInputStream(new byte[] {});
- }
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/MultipartEntity.java b/core/java/com/android/internal/http/multipart/MultipartEntity.java
deleted file mode 100644
index 5319251..0000000
--- a/core/java/com/android/internal/http/multipart/MultipartEntity.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/MultipartRequestEntity.java,v 1.1 2004/10/06 03:39:59 mbecke Exp $
- * $Revision: 502647 $
- * $Date: 2007-02-02 17:22:54 +0100 (Fri, 02 Feb 2007) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Random;
-
-import org.apache.http.Header;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.params.HttpParams;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Implements a request entity suitable for an HTTP multipart POST method.
- * <p>
- * The HTTP multipart POST method is defined in section 3.3 of
- * <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC1867</a>:
- * <blockquote>
- * The media-type multipart/form-data follows the rules of all multipart
- * MIME data streams as outlined in RFC 1521. The multipart/form-data contains
- * a series of parts. Each part is expected to contain a content-disposition
- * header where the value is "form-data" and a name attribute specifies
- * the field name within the form, e.g., 'content-disposition: form-data;
- * name="xxxxx"', where xxxxx is the field name corresponding to that field.
- * Field names originally in non-ASCII character sets may be encoded using
- * the method outlined in RFC 1522.
- * </blockquote>
- * </p>
- * <p>This entity is designed to be used in conjunction with the
- * {@link org.apache.http.HttpRequest} to provide
- * multipart posts. Example usage:</p>
- * <pre>
- * File f = new File("/path/fileToUpload.txt");
- * HttpRequest request = new HttpRequest("http://host/some_path");
- * Part[] parts = {
- * new StringPart("param_name", "value"),
- * new FilePart(f.getName(), f)
- * };
- * filePost.setEntity(
- * new MultipartRequestEntity(parts, filePost.getParams())
- * );
- * HttpClient client = new HttpClient();
- * int status = client.executeMethod(filePost);
- * </pre>
- *
- * @since 3.0
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead.
- * The Apache HTTP client is no longer maintained and may be removed in a future
- * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
- * for further details.
- */
-@Deprecated
-public class MultipartEntity extends AbstractHttpEntity {
-
- private static final Log log = LogFactory.getLog(MultipartEntity.class);
-
- /** The Content-Type for multipart/form-data. */
- private static final String MULTIPART_FORM_CONTENT_TYPE = "multipart/form-data";
-
- /**
- * Sets the value to use as the multipart boundary.
- * <p>
- * This parameter expects a value if type {@link String}.
- * </p>
- */
- public static final String MULTIPART_BOUNDARY = "http.method.multipart.boundary";
-
- /**
- * The pool of ASCII chars to be used for generating a multipart boundary.
- */
- private static byte[] MULTIPART_CHARS = EncodingUtils.getAsciiBytes(
- "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
- /**
- * Generates a random multipart boundary string.
- */
- private static byte[] generateMultipartBoundary() {
- Random rand = new Random();
- byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)];
- }
- return bytes;
- }
-
- /** The MIME parts as set by the constructor */
- protected Part[] parts;
-
- private byte[] multipartBoundary;
-
- private HttpParams params;
-
- private boolean contentConsumed = false;
-
- /**
- * Creates a new multipart entity containing the given parts.
- * @param parts The parts to include.
- * @param params The params of the HttpMethod using this entity.
- */
- public MultipartEntity(Part[] parts, HttpParams params) {
- if (parts == null) {
- throw new IllegalArgumentException("parts cannot be null");
- }
- if (params == null) {
- throw new IllegalArgumentException("params cannot be null");
- }
- this.parts = parts;
- this.params = params;
- }
-
- public MultipartEntity(Part[] parts) {
- setContentType(MULTIPART_FORM_CONTENT_TYPE);
- if (parts == null) {
- throw new IllegalArgumentException("parts cannot be null");
- }
- this.parts = parts;
- this.params = null;
- }
-
- /**
- * Returns the MIME boundary string that is used to demarcate boundaries of
- * this part. The first call to this method will implicitly create a new
- * boundary string. To create a boundary string first the
- * HttpMethodParams.MULTIPART_BOUNDARY parameter is considered. Otherwise
- * a random one is generated.
- *
- * @return The boundary string of this entity in ASCII encoding.
- */
- protected byte[] getMultipartBoundary() {
- if (multipartBoundary == null) {
- String temp = null;
- if (params != null) {
- temp = (String) params.getParameter(MULTIPART_BOUNDARY);
- }
- if (temp != null) {
- multipartBoundary = EncodingUtils.getAsciiBytes(temp);
- } else {
- multipartBoundary = generateMultipartBoundary();
- }
- }
- return multipartBoundary;
- }
-
- /**
- * Returns <code>true</code> if all parts are repeatable, <code>false</code> otherwise.
- */
- public boolean isRepeatable() {
- for (int i = 0; i < parts.length; i++) {
- if (!parts[i].isRepeatable()) {
- return false;
- }
- }
- return true;
- }
-
- /* (non-Javadoc)
- */
- public void writeTo(OutputStream out) throws IOException {
- Part.sendParts(out, parts, getMultipartBoundary());
- }
- /* (non-Javadoc)
- * @see org.apache.commons.http.AbstractHttpEntity.#getContentType()
- */
- @Override
- public Header getContentType() {
- StringBuffer buffer = new StringBuffer(MULTIPART_FORM_CONTENT_TYPE);
- buffer.append("; boundary=");
- buffer.append(EncodingUtils.getAsciiString(getMultipartBoundary()));
- return new BasicHeader(HTTP.CONTENT_TYPE, buffer.toString());
-
- }
-
- /* (non-Javadoc)
- */
- public long getContentLength() {
- try {
- return Part.getLengthOfParts(parts, getMultipartBoundary());
- } catch (Exception e) {
- log.error("An exception occurred while getting the length of the parts", e);
- return 0;
- }
- }
-
- public InputStream getContent() throws IOException, IllegalStateException {
- if(!isRepeatable() && this.contentConsumed ) {
- throw new IllegalStateException("Content has been consumed");
- }
- this.contentConsumed = true;
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Part.sendParts(baos, this.parts, this.multipartBoundary);
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- return bais;
- }
-
- public boolean isStreaming() {
- return false;
- }
-}
diff --git a/core/java/com/android/internal/http/multipart/Part.java b/core/java/com/android/internal/http/multipart/Part.java
deleted file mode 100644
index 1d66dc67..0000000
--- a/core/java/com/android/internal/http/multipart/Part.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/Part.java,v 1.16 2005/01/14 21:16:40 olegk Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Abstract class for one Part of a multipart post object.
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead.
- * The Apache HTTP client is no longer maintained and may be removed in a future
- * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
- * for further details.
- */
-@Deprecated
-public abstract class Part {
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(Part.class);
-
- /**
- * The boundary
- * @deprecated use {@link org.apache.http.client.methods.multipart#MULTIPART_BOUNDARY}
- */
- protected static final String BOUNDARY = "----------------314159265358979323846";
-
- /**
- * The boundary as a byte array.
- * @deprecated
- */
- protected static final byte[] BOUNDARY_BYTES = EncodingUtils.getAsciiBytes(BOUNDARY);
-
- /**
- * The default boundary to be used if {@link #setPartBoundary(byte[])} has not
- * been called.
- */
- private static final byte[] DEFAULT_BOUNDARY_BYTES = BOUNDARY_BYTES;
-
- /** Carriage return/linefeed */
- protected static final String CRLF = "\r\n";
-
- /** Carriage return/linefeed as a byte array */
- protected static final byte[] CRLF_BYTES = EncodingUtils.getAsciiBytes(CRLF);
-
- /** Content dispostion characters */
- protected static final String QUOTE = "\"";
-
- /** Content dispostion as a byte array */
- protected static final byte[] QUOTE_BYTES =
- EncodingUtils.getAsciiBytes(QUOTE);
-
- /** Extra characters */
- protected static final String EXTRA = "--";
-
- /** Extra characters as a byte array */
- protected static final byte[] EXTRA_BYTES =
- EncodingUtils.getAsciiBytes(EXTRA);
-
- /** Content dispostion characters */
- protected static final String CONTENT_DISPOSITION = "Content-Disposition: form-data; name=";
-
- /** Content dispostion as a byte array */
- protected static final byte[] CONTENT_DISPOSITION_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_DISPOSITION);
-
- /** Content type header */
- protected static final String CONTENT_TYPE = "Content-Type: ";
-
- /** Content type header as a byte array */
- protected static final byte[] CONTENT_TYPE_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_TYPE);
-
- /** Content charset */
- protected static final String CHARSET = "; charset=";
-
- /** Content charset as a byte array */
- protected static final byte[] CHARSET_BYTES =
- EncodingUtils.getAsciiBytes(CHARSET);
-
- /** Content type header */
- protected static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding: ";
-
- /** Content type header as a byte array */
- protected static final byte[] CONTENT_TRANSFER_ENCODING_BYTES =
- EncodingUtils.getAsciiBytes(CONTENT_TRANSFER_ENCODING);
-
- /**
- * Return the boundary string.
- * @return the boundary string
- * @deprecated uses a constant string. Rather use {@link #getPartBoundary}
- */
- public static String getBoundary() {
- return BOUNDARY;
- }
-
- /**
- * The ASCII bytes to use as the multipart boundary.
- */
- private byte[] boundaryBytes;
-
- /**
- * Return the name of this part.
- * @return The name.
- */
- public abstract String getName();
-
- /**
- * Returns the content type of this part.
- * @return the content type, or <code>null</code> to exclude the content type header
- */
- public abstract String getContentType();
-
- /**
- * Return the character encoding of this part.
- * @return the character encoding, or <code>null</code> to exclude the character
- * encoding header
- */
- public abstract String getCharSet();
-
- /**
- * Return the transfer encoding of this part.
- * @return the transfer encoding, or <code>null</code> to exclude the transfer encoding header
- */
- public abstract String getTransferEncoding();
-
- /**
- * Gets the part boundary to be used.
- * @return the part boundary as an array of bytes.
- *
- * @since 3.0
- */
- protected byte[] getPartBoundary() {
- if (boundaryBytes == null) {
- // custom boundary bytes have not been set, use the default.
- return DEFAULT_BOUNDARY_BYTES;
- } else {
- return boundaryBytes;
- }
- }
-
- /**
- * Sets the part boundary. Only meant to be used by
- * {@link Part#sendParts(OutputStream, Part[], byte[])}
- * and {@link Part#getLengthOfParts(Part[], byte[])}
- * @param boundaryBytes An array of ASCII bytes.
- * @since 3.0
- */
- void setPartBoundary(byte[] boundaryBytes) {
- this.boundaryBytes = boundaryBytes;
- }
-
- /**
- * Tests if this part can be sent more than once.
- * @return <code>true</code> if {@link #sendData(OutputStream)} can be successfully called
- * more than once.
- * @since 3.0
- */
- public boolean isRepeatable() {
- return true;
- }
-
- /**
- * Write the start to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendStart(OutputStream out) throws IOException {
- LOG.trace("enter sendStart(OutputStream out)");
- out.write(EXTRA_BYTES);
- out.write(getPartBoundary());
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write the content disposition header to the specified output stream
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendDispositionHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendDispositionHeader(OutputStream out)");
- out.write(CONTENT_DISPOSITION_BYTES);
- out.write(QUOTE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(getName()));
- out.write(QUOTE_BYTES);
- }
-
- /**
- * Write the content type header to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendContentTypeHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendContentTypeHeader(OutputStream out)");
- String contentType = getContentType();
- if (contentType != null) {
- out.write(CRLF_BYTES);
- out.write(CONTENT_TYPE_BYTES);
- out.write(EncodingUtils.getAsciiBytes(contentType));
- String charSet = getCharSet();
- if (charSet != null) {
- out.write(CHARSET_BYTES);
- out.write(EncodingUtils.getAsciiBytes(charSet));
- }
- }
- }
-
- /**
- * Write the content transfer encoding header to the specified
- * output stream
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
- String transferEncoding = getTransferEncoding();
- if (transferEncoding != null) {
- out.write(CRLF_BYTES);
- out.write(CONTENT_TRANSFER_ENCODING_BYTES);
- out.write(EncodingUtils.getAsciiBytes(transferEncoding));
- }
- }
-
- /**
- * Write the end of the header to the output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendEndOfHeader(OutputStream out) throws IOException {
- LOG.trace("enter sendEndOfHeader(OutputStream out)");
- out.write(CRLF_BYTES);
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write the data to the specified output stream
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected abstract void sendData(OutputStream out) throws IOException;
-
- /**
- * Return the length of the main content
- *
- * @return long The length.
- * @throws IOException If an IO problem occurs
- */
- protected abstract long lengthOfData() throws IOException;
-
- /**
- * Write the end data to the output stream.
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- protected void sendEnd(OutputStream out) throws IOException {
- LOG.trace("enter sendEnd(OutputStream out)");
- out.write(CRLF_BYTES);
- }
-
- /**
- * Write all the data to the output stream.
- * If you override this method make sure to override
- * #length() as well
- *
- * @param out The output stream
- * @throws IOException If an IO problem occurs.
- */
- public void send(OutputStream out) throws IOException {
- LOG.trace("enter send(OutputStream out)");
- sendStart(out);
- sendDispositionHeader(out);
- sendContentTypeHeader(out);
- sendTransferEncodingHeader(out);
- sendEndOfHeader(out);
- sendData(out);
- sendEnd(out);
- }
-
-
- /**
- * Return the full length of all the data.
- * If you override this method make sure to override
- * #send(OutputStream) as well
- *
- * @return long The length.
- * @throws IOException If an IO problem occurs
- */
- public long length() throws IOException {
- LOG.trace("enter length()");
- if (lengthOfData() < 0) {
- return -1;
- }
- ByteArrayOutputStream overhead = new ByteArrayOutputStream();
- sendStart(overhead);
- sendDispositionHeader(overhead);
- sendContentTypeHeader(overhead);
- sendTransferEncodingHeader(overhead);
- sendEndOfHeader(overhead);
- sendEnd(overhead);
- return overhead.size() + lengthOfData();
- }
-
- /**
- * Return a string representation of this object.
- * @return A string representation of this object.
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return this.getName();
- }
-
- /**
- * Write all parts and the last boundary to the specified output stream.
- *
- * @param out The stream to write to.
- * @param parts The parts to write.
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- */
- public static void sendParts(OutputStream out, final Part[] parts)
- throws IOException {
- sendParts(out, parts, DEFAULT_BOUNDARY_BYTES);
- }
-
- /**
- * Write all parts and the last boundary to the specified output stream.
- *
- * @param out The stream to write to.
- * @param parts The parts to write.
- * @param partBoundary The ASCII bytes to use as the part boundary.
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- *
- * @since 3.0
- */
- public static void sendParts(OutputStream out, Part[] parts, byte[] partBoundary)
- throws IOException {
-
- if (parts == null) {
- throw new IllegalArgumentException("Parts may not be null");
- }
- if (partBoundary == null || partBoundary.length == 0) {
- throw new IllegalArgumentException("partBoundary may not be empty");
- }
- for (int i = 0; i < parts.length; i++) {
- // set the part boundary before the part is sent
- parts[i].setPartBoundary(partBoundary);
- parts[i].send(out);
- }
- out.write(EXTRA_BYTES);
- out.write(partBoundary);
- out.write(EXTRA_BYTES);
- out.write(CRLF_BYTES);
- }
-
- /**
- * Return the total sum of all parts and that of the last boundary
- *
- * @param parts The parts.
- * @return The total length
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- */
- public static long getLengthOfParts(Part[] parts)
- throws IOException {
- return getLengthOfParts(parts, DEFAULT_BOUNDARY_BYTES);
- }
-
- /**
- * Gets the length of the multipart message including the given parts.
- *
- * @param parts The parts.
- * @param partBoundary The ASCII bytes to use as the part boundary.
- * @return The total length
- *
- * @throws IOException If an I/O error occurs while writing the parts.
- *
- * @since 3.0
- */
- public static long getLengthOfParts(Part[] parts, byte[] partBoundary) throws IOException {
- LOG.trace("getLengthOfParts(Parts[])");
- if (parts == null) {
- throw new IllegalArgumentException("Parts may not be null");
- }
- long total = 0;
- for (int i = 0; i < parts.length; i++) {
- // set the part boundary before we calculate the part's length
- parts[i].setPartBoundary(partBoundary);
- long l = parts[i].length();
- if (l < 0) {
- return -1;
- }
- total += l;
- }
- total += EXTRA_BYTES.length;
- total += partBoundary.length;
- total += EXTRA_BYTES.length;
- total += CRLF_BYTES.length;
- return total;
- }
-}
diff --git a/core/java/com/android/internal/http/multipart/PartBase.java b/core/java/com/android/internal/http/multipart/PartBase.java
deleted file mode 100644
index 876d15d..0000000
--- a/core/java/com/android/internal/http/multipart/PartBase.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartBase.java,v 1.5 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-
-/**
- * Provides setters and getters for the basic Part properties.
- *
- * @author Michael Becke
- */
-public abstract class PartBase extends Part {
-
- /** Name of the file part. */
- private String name;
-
- /** Content type of the file part. */
- private String contentType;
-
- /** Content encoding of the file part. */
- private String charSet;
-
- /** The transfer encoding. */
- private String transferEncoding;
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param contentType The content type, or <code>null</code>
- * @param charSet The character encoding, or <code>null</code>
- * @param transferEncoding The transfer encoding, or <code>null</code>
- */
- public PartBase(String name, String contentType, String charSet, String transferEncoding) {
-
- if (name == null) {
- throw new IllegalArgumentException("Name must not be null");
- }
- this.name = name;
- this.contentType = contentType;
- this.charSet = charSet;
- this.transferEncoding = transferEncoding;
- }
-
- /**
- * Returns the name.
- * @return The name.
- * @see Part#getName()
- */
- @Override
- public String getName() {
- return this.name;
- }
-
- /**
- * Returns the content type of this part.
- * @return String The name.
- */
- @Override
- public String getContentType() {
- return this.contentType;
- }
-
- /**
- * Return the character encoding of this part.
- * @return String The name.
- */
- @Override
- public String getCharSet() {
- return this.charSet;
- }
-
- /**
- * Returns the transfer encoding of this part.
- * @return String The name.
- */
- @Override
- public String getTransferEncoding() {
- return transferEncoding;
- }
-
- /**
- * Sets the character encoding.
- *
- * @param charSet the character encoding, or <code>null</code> to exclude the character
- * encoding header
- */
- public void setCharSet(String charSet) {
- this.charSet = charSet;
- }
-
- /**
- * Sets the content type.
- *
- * @param contentType the content type, or <code>null</code> to exclude the content type header
- */
- public void setContentType(String contentType) {
- this.contentType = contentType;
- }
-
- /**
- * Sets the part name.
- *
- * @param name
- */
- public void setName(String name) {
- if (name == null) {
- throw new IllegalArgumentException("Name must not be null");
- }
- this.name = name;
- }
-
- /**
- * Sets the transfer encoding.
- *
- * @param transferEncoding the transfer encoding, or <code>null</code> to exclude the
- * transfer encoding header
- */
- public void setTransferEncoding(String transferEncoding) {
- this.transferEncoding = transferEncoding;
- }
-
-}
diff --git a/core/java/com/android/internal/http/multipart/PartSource.java b/core/java/com/android/internal/http/multipart/PartSource.java
deleted file mode 100644
index 3740696..0000000
--- a/core/java/com/android/internal/http/multipart/PartSource.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/PartSource.java,v 1.6 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * An interface for providing access to data when posting MultiPart messages.
- *
- * @see FilePart
- *
- * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
- *
- * @since 2.0
- */
-public interface PartSource {
-
- /**
- * Gets the number of bytes contained in this source.
- *
- * @return a value >= 0
- */
- long getLength();
-
- /**
- * Gets the name of the file this source represents.
- *
- * @return the fileName used for posting a MultiPart file part
- */
- String getFileName();
-
- /**
- * Gets a new InputStream for reading this source. This method can be
- * called more than once and should therefore return a new stream every
- * time.
- *
- * @return a new InputStream
- *
- * @throws IOException if an error occurs when creating the InputStream
- */
- InputStream createInputStream() throws IOException;
-
-}
diff --git a/core/java/com/android/internal/http/multipart/StringPart.java b/core/java/com/android/internal/http/multipart/StringPart.java
deleted file mode 100644
index 73d0f90..0000000
--- a/core/java/com/android/internal/http/multipart/StringPart.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/methods/multipart/StringPart.java,v 1.11 2004/04/18 23:51:37 jsdever Exp $
- * $Revision: 480424 $
- * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
- *
- * ====================================================================
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- */
-
-package com.android.internal.http.multipart;
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-import org.apache.http.util.EncodingUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Simple string parameter for a multipart post
- *
- * @author <a href="mailto:mattalbright@yahoo.com">Matthew Albright</a>
- * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
- * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
- * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
- *
- * @since 2.0
- *
- * @deprecated Please use {@link java.net.URLConnection} and friends instead.
- * The Apache HTTP client is no longer maintained and may be removed in a future
- * release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
- * for further details.
- */
-@Deprecated
-public class StringPart extends PartBase {
-
- /** Log object for this class. */
- private static final Log LOG = LogFactory.getLog(StringPart.class);
-
- /** Default content encoding of string parameters. */
- public static final String DEFAULT_CONTENT_TYPE = "text/plain";
-
- /** Default charset of string parameters*/
- public static final String DEFAULT_CHARSET = "US-ASCII";
-
- /** Default transfer encoding of string parameters*/
- public static final String DEFAULT_TRANSFER_ENCODING = "8bit";
-
- /** Contents of this StringPart. */
- private byte[] content;
-
- /** The String value of this part. */
- private String value;
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param value the string to post
- * @param charset the charset to be used to encode the string, if <code>null</code>
- * the {@link #DEFAULT_CHARSET default} is used
- */
- public StringPart(String name, String value, String charset) {
-
- super(
- name,
- DEFAULT_CONTENT_TYPE,
- charset == null ? DEFAULT_CHARSET : charset,
- DEFAULT_TRANSFER_ENCODING
- );
- if (value == null) {
- throw new IllegalArgumentException("Value may not be null");
- }
- if (value.indexOf(0) != -1) {
- // See RFC 2048, 2.8. "8bit Data"
- throw new IllegalArgumentException("NULs may not be present in string parts");
- }
- this.value = value;
- }
-
- /**
- * Constructor.
- *
- * @param name The name of the part
- * @param value the string to post
- */
- public StringPart(String name, String value) {
- this(name, value, null);
- }
-
- /**
- * Gets the content in bytes. Bytes are lazily created to allow the charset to be changed
- * after the part is created.
- *
- * @return the content in bytes
- */
- private byte[] getContent() {
- if (content == null) {
- content = EncodingUtils.getBytes(value, getCharSet());
- }
- return content;
- }
-
- /**
- * Writes the data to the given OutputStream.
- * @param out the OutputStream to write to
- * @throws IOException if there is a write error
- */
- @Override
- protected void sendData(OutputStream out) throws IOException {
- LOG.trace("enter sendData(OutputStream)");
- out.write(getContent());
- }
-
- /**
- * Return the length of the data.
- * @return The length of the data.
- * @see Part#lengthOfData()
- */
- @Override
- protected long lengthOfData() {
- LOG.trace("enter lengthOfData()");
- return getContent().length;
- }
-
- /* (non-Javadoc)
- * @see org.apache.commons.httpclient.methods.multipart.BasePart#setCharSet(java.lang.String)
- */
- @Override
- public void setCharSet(String charSet) {
- super.setCharSet(charSet);
- this.content = null;
- }
-
-}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 183527cb..9aa36d3 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -35,6 +35,8 @@
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.TextServicesManager;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -409,6 +411,24 @@
return false;
}
+ public static Locale constructLocaleFromString(String localeStr) {
+ if (TextUtils.isEmpty(localeStr)) {
+ return null;
+ }
+ // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
+ String[] localeParams = localeStr.split("_", 3);
+ // The length of localeStr is guaranteed to always return a 1 <= value <= 3
+ // because localeStr is not empty.
+ if (localeParams.length == 1) {
+ return new Locale(localeParams[0]);
+ } else if (localeParams.length == 2) {
+ return new Locale(localeParams[0], localeParams[1]);
+ } else if (localeParams.length == 3) {
+ return new Locale(localeParams[0], localeParams[1], localeParams[2]);
+ }
+ return null;
+ }
+
public static boolean containsSubtypeOf(final InputMethodInfo imi,
@Nullable final Locale locale, final boolean checkCountry, final String mode) {
if (locale == null) {
@@ -418,15 +438,16 @@
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
if (checkCountry) {
- // TODO: Use {@link Locale#toLanguageTag()} and
- // {@link Locale#forLanguageTag(languageTag)} instead.
- if (!TextUtils.equals(subtype.getLocale(), locale.toString())) {
+ final Locale subtypeLocale = constructLocaleFromString(subtype.getLocale());
+ if (subtypeLocale == null ||
+ !TextUtils.equals(subtypeLocale.getLanguage(), locale.getLanguage()) ||
+ !TextUtils.equals(subtypeLocale.getCountry(), locale.getCountry())) {
continue;
}
} else {
final Locale subtypeLocale = new Locale(getLanguageFromLocaleString(
subtype.getLocale()));
- if (!subtypeLocale.getLanguage().equals(locale.getLanguage())) {
+ if (!TextUtils.equals(subtypeLocale.getLanguage(), locale.getLanguage())) {
continue;
}
}
@@ -518,7 +539,8 @@
return NOT_A_SUBTYPE_ID;
}
- private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
+ @VisibleForTesting
+ public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
Resources res, InputMethodInfo imi) {
final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
final String systemLocale = res.getConfiguration().locale.toString();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 20bb95e..d0c7f8c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -94,7 +94,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 116 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 118 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -208,7 +208,7 @@
final HistoryItem mHistoryLastLastWritten = new HistoryItem();
final HistoryItem mHistoryReadTmp = new HistoryItem();
final HistoryItem mHistoryAddTmp = new HistoryItem();
- final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap<HistoryTag, Integer>();
+ final HashMap<HistoryTag, Integer> mHistoryTagPool = new HashMap();
String[] mReadHistoryStrings;
int[] mReadHistoryUids;
int mReadHistoryChars;
@@ -227,6 +227,38 @@
HistoryItem mHistoryLastEnd;
HistoryItem mHistoryCache;
+ // Used by computeHistoryStepDetails
+ HistoryStepDetails mLastHistoryStepDetails = null;
+ byte mLastHistoryStepLevel = 0;
+ final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
+ final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
+ /**
+ * Total time (in 1/100 sec) spent executing in user code.
+ */
+ long mLastStepCpuUserTime;
+ long mCurStepCpuUserTime;
+ /**
+ * Total time (in 1/100 sec) spent executing in kernel code.
+ */
+ long mLastStepCpuSystemTime;
+ long mCurStepCpuSystemTime;
+ /**
+ * Times from /proc/stat
+ */
+ long mLastStepStatUserTime;
+ long mLastStepStatSystemTime;
+ long mLastStepStatIOWaitTime;
+ long mLastStepStatIrqTime;
+ long mLastStepStatSoftIrqTime;
+ long mLastStepStatIdleTime;
+ long mCurStepStatUserTime;
+ long mCurStepStatSystemTime;
+ long mCurStepStatIOWaitTime;
+ long mCurStepStatIrqTime;
+ long mCurStepStatSoftIrqTime;
+ long mCurStepStatIdleTime;
+
private HistoryItem mHistoryIterator;
private boolean mReadOverflow;
private boolean mIteratingHistory;
@@ -1938,6 +1970,10 @@
static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
static final int STATE_BATTERY_PLUG_SHIFT = 24;
+ // We use the low bit of the battery state int to indicate that we have full details
+ // from a battery level change.
+ static final int BATTERY_DELTA_LEVEL_FLAG = 0x00000001;
+
public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
dest.writeInt(DELTA_TIME_ABS);
@@ -1958,7 +1994,11 @@
deltaTimeToken = (int)deltaTime;
}
int firstToken = deltaTimeToken | (cur.states&DELTA_STATE_MASK);
- final int batteryLevelInt = buildBatteryLevelInt(cur);
+ final int includeStepDetails = mLastHistoryStepLevel > cur.batteryLevel
+ ? BATTERY_DELTA_LEVEL_FLAG : 0;
+ final boolean computeStepDetails = includeStepDetails != 0
+ || mLastHistoryStepDetails == null;
+ final int batteryLevelInt = buildBatteryLevelInt(cur) | includeStepDetails;
final boolean batteryLevelIntChanged = batteryLevelInt != lastBatteryLevelInt;
if (batteryLevelIntChanged) {
firstToken |= DELTA_BATTERY_LEVEL_FLAG;
@@ -2040,12 +2080,26 @@
+ cur.eventTag.poolIdx + " " + cur.eventTag.uid + ":"
+ cur.eventTag.string);
}
+ if (computeStepDetails) {
+ computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
+ if (includeStepDetails != 0) {
+ mCurHistoryStepDetails.writeToParcel(dest);
+ }
+ cur.stepDetails = mCurHistoryStepDetails;
+ mLastHistoryStepDetails = mCurHistoryStepDetails;
+ } else {
+ cur.stepDetails = null;
+ }
+ if (mLastHistoryStepLevel < cur.batteryLevel) {
+ mLastHistoryStepDetails = null;
+ }
+ mLastHistoryStepLevel = cur.batteryLevel;
}
private int buildBatteryLevelInt(HistoryItem h) {
return ((((int)h.batteryLevel)<<25)&0xfe000000)
- | ((((int)h.batteryTemperature)<<14)&0x01ffc000)
- | (((int)h.batteryVoltage)&0x00003fff);
+ | ((((int)h.batteryTemperature)<<14)&0x01ff8000)
+ | ((((int)h.batteryVoltage)<<1)&0x00007fff);
}
private int buildStateInt(HistoryItem h) {
@@ -2063,6 +2117,98 @@
| (h.states&(~DELTA_STATE_MASK));
}
+ private void computeHistoryStepDetails(final HistoryStepDetails out,
+ final HistoryStepDetails last) {
+ final HistoryStepDetails tmp = last != null ? mTmpHistoryStepDetails : out;
+
+ // Perform a CPU update right after we do this collection, so we have started
+ // collecting good data for the next step.
+ requestImmediateCpuUpdate();
+
+ if (last == null) {
+ // We are not generating a delta, so all we need to do is reset the stats
+ // we will later be doing a delta from.
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ tmp.clear();
+ return;
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys="
+ + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime
+ + " irq=" + mLastStepStatIrqTime + " sirq="
+ + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime);
+ Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys="
+ + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime
+ + " irq=" + mCurStepStatIrqTime + " sirq="
+ + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime);
+ }
+ out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime);
+ out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime);
+ out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime);
+ out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime);
+ out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime);
+ out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime);
+ out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime);
+ out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime);
+ out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1;
+ out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0;
+ out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0;
+ final int NU = mUidStats.size();
+ for (int i=0; i<NU; i++) {
+ final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i);
+ final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime);
+ final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime);
+ final int totalTime = totalUTime + totalSTime;
+ uid.mLastStepUserTime = uid.mCurStepUserTime;
+ uid.mLastStepSystemTime = uid.mCurStepSystemTime;
+ if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) {
+ continue;
+ }
+ if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) {
+ out.appCpuUid3 = uid.mUid;
+ out.appCpuUTime3 = totalUTime;
+ out.appCpuSTime3 = totalSTime;
+ } else {
+ out.appCpuUid3 = out.appCpuUid2;
+ out.appCpuUTime3 = out.appCpuUTime2;
+ out.appCpuSTime3 = out.appCpuSTime2;
+ if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) {
+ out.appCpuUid2 = uid.mUid;
+ out.appCpuUTime2 = totalUTime;
+ out.appCpuSTime2 = totalSTime;
+ } else {
+ out.appCpuUid2 = out.appCpuUid1;
+ out.appCpuUTime2 = out.appCpuUTime1;
+ out.appCpuSTime2 = out.appCpuSTime1;
+ out.appCpuUid1 = uid.mUid;
+ out.appCpuUTime1 = totalUTime;
+ out.appCpuSTime1 = totalSTime;
+ }
+ }
+ }
+ mLastStepCpuUserTime = mCurStepCpuUserTime;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime;
+ mLastStepStatUserTime = mCurStepStatUserTime;
+ mLastStepStatSystemTime = mCurStepStatSystemTime;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime;
+ mLastStepStatIrqTime = mCurStepStatIrqTime;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime;
+ mLastStepStatIdleTime = mCurStepStatIdleTime;
+ }
+
public void readHistoryDelta(Parcel src, HistoryItem cur) {
int firstToken = src.readInt();
int deltaTimeToken = firstToken&DELTA_TIME_MASK;
@@ -2091,8 +2237,9 @@
cur.numReadInts += 2;
}
+ final int batteryLevelInt;
if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) {
- int batteryLevelInt = src.readInt();
+ batteryLevelInt = src.readInt();
cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f);
cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21);
cur.batteryVoltage = (char)(batteryLevelInt&0x3fff);
@@ -2102,6 +2249,8 @@
+ " batteryLevel=" + cur.batteryLevel
+ " batteryTemp=" + cur.batteryTemperature
+ " batteryVolt=" + (int)cur.batteryVoltage);
+ } else {
+ batteryLevelInt = 0;
}
if ((firstToken&DELTA_STATE_FLAG) != 0) {
@@ -2180,6 +2329,13 @@
} else {
cur.eventCode = HistoryItem.EVENT_NONE;
}
+
+ if ((batteryLevelInt&BATTERY_DELTA_LEVEL_FLAG) != 0) {
+ cur.stepDetails = mReadHistoryStepDetails;
+ cur.stepDetails.readFromParcel(src);
+ } else {
+ cur.stepDetails = null;
+ }
}
@Override
@@ -2207,6 +2363,7 @@
&& (diffStates2&lastDiffStates2) == 0
&& (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null)
&& (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null)
+ && mHistoryLastWritten.stepDetails == null
&& (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
|| cur.eventCode == HistoryItem.EVENT_NONE)
&& mHistoryLastWritten.batteryLevel == cur.batteryLevel
@@ -2632,6 +2789,11 @@
}
}
+ private void requestImmediateCpuUpdate() {
+ mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ mHandler.sendEmptyMessage(MSG_UPDATE_WAKELOCKS);
+ }
+
public void setRecordAllHistoryLocked(boolean enabled) {
mRecordAllHistory = enabled;
if (!enabled) {
@@ -2823,6 +2985,10 @@
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
+ if (!mOnBatteryInternal) {
+ return -1;
+ }
+
final int N = mPartialTimers.size();
if (N == 0) {
mLastPartialTimers.clear();
@@ -2853,7 +3019,23 @@
return 0;
}
- public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
+ public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
+ int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
+ int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime,
+ long[] cpuSpeedTimes) {
+ if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
+ + " user=" + statUserTime + " sys=" + statSystemTime
+ + " io=" + statIOWaitTime + " irq=" + statIrqTime
+ + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime);
+ mCurStepCpuUserTime += totalUTime;
+ mCurStepCpuSystemTime += totalSTime;
+ mCurStepStatUserTime += statUserTime;
+ mCurStepStatSystemTime += statSystemTime;
+ mCurStepStatIOWaitTime += statIOWaitTime;
+ mCurStepStatIrqTime += statIrqTime;
+ mCurStepStatSoftIrqTime += statSoftIrqTime;
+ mCurStepStatIdleTime += statIdleTime;
+
final int N = mPartialTimers.size();
if (perc != 0) {
int num = 0;
@@ -2874,26 +3056,24 @@
if (st.mInList) {
Uid uid = st.mUid;
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
- int myUTime = utime/num;
- int mySTime = stime/num;
- utime -= myUTime;
- stime -= mySTime;
+ int myUTime = remainUTime/num;
+ int mySTime = remainSTtime/num;
+ remainUTime -= myUTime;
+ remainSTtime -= mySTime;
num--;
Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
- proc.addCpuTimeLocked(myUTime, mySTime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(myUTime, mySTime, cpuSpeedTimes);
}
}
}
}
// Just in case, collect any lost CPU time.
- if (utime != 0 || stime != 0) {
+ if (remainUTime != 0 || remainSTtime != 0) {
Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
if (uid != null) {
Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
- proc.addCpuTimeLocked(utime, stime);
- proc.addSpeedStepTimes(cpuSpeedTimes);
+ proc.addCpuTimeLocked(remainUTime, remainSTtime, cpuSpeedTimes);
}
}
}
@@ -4214,6 +4394,14 @@
LongSamplingCounter mMobileRadioActiveCount;
/**
+ * The CPU times we had at the last history details update.
+ */
+ long mLastStepUserTime;
+ long mLastStepSystemTime;
+ long mCurStepUserTime;
+ long mCurStepSystemTime;
+
+ /**
* The statistics we have collected for this uid's wake locks.
*/
final OverflowArrayMap<Wakelock> mWakelockStats = new OverflowArrayMap<Wakelock>() {
@@ -4876,6 +5064,9 @@
mPackageStats.clear();
}
+ mLastStepUserTime = mLastStepSystemTime = 0;
+ mCurStepUserTime = mCurStepSystemTime = 0;
+
if (!active) {
if (mWifiRunningTimer != null) {
mWifiRunningTimer.detach();
@@ -5678,9 +5869,22 @@
return BatteryStatsImpl.this;
}
- public void addCpuTimeLocked(int utime, int stime) {
+ public void addCpuTimeLocked(int utime, int stime, long[] speedStepBins) {
mUserTime += utime;
+ mCurStepUserTime += utime;
mSystemTime += stime;
+ mCurStepSystemTime += stime;
+
+ for (int i = 0; i < mSpeedBins.length && i < speedStepBins.length; i++) {
+ long amt = speedStepBins[i];
+ if (amt != 0) {
+ SamplingCounter c = mSpeedBins[i];
+ if (c == null) {
+ mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
+ }
+ c.addCountAtomic(speedStepBins[i]);
+ }
+ }
}
public void addForegroundTimeLocked(long ttime) {
@@ -5770,20 +5974,6 @@
return val;
}
- /* Called by ActivityManagerService when CPU times are updated. */
- public void addSpeedStepTimes(long[] values) {
- for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
- long amt = values[i];
- if (amt != 0) {
- SamplingCounter c = mSpeedBins[i];
- if (c == null) {
- mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
- }
- c.addCountAtomic(values[i]);
- }
- }
- }
-
@Override
public long getTimeAtCpuSpeedStep(int speedStep, int which) {
if (speedStep < mSpeedBins.length) {
@@ -6756,6 +6946,18 @@
mWakeupReasonStats.clear();
}
+ mLastHistoryStepDetails = null;
+ mLastStepCpuUserTime = mLastStepCpuSystemTime = 0;
+ mCurStepCpuUserTime = mCurStepCpuSystemTime = 0;
+ mLastStepCpuUserTime = mCurStepCpuUserTime = 0;
+ mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0;
+ mLastStepStatUserTime = mCurStepStatUserTime = 0;
+ mLastStepStatSystemTime = mCurStepStatSystemTime = 0;
+ mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0;
+ mLastStepStatIrqTime = mCurStepStatIrqTime = 0;
+ mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0;
+ mLastStepStatIdleTime = mCurStepStatIdleTime = 0;
+
initDischarge();
clearHistoryLocked();
@@ -6872,7 +7074,7 @@
reset = true;
mNumDischargeStepDurations = 0;
}
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = true;
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
mLastDischargeStepTime = -1;
@@ -6900,7 +7102,7 @@
mDischargeAmountScreenOff = 0;
updateTimeBasesLocked(true, !screenOn, uptime, realtime);
} else {
- mOnBattery = mOnBatteryInternal = onBattery;
+ mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index b5338df..501e0ec 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -152,6 +152,7 @@
private int mRelIrqTime;
private int mRelSoftIrqTime;
private int mRelIdleTime;
+ private boolean mRelStatsAreGood;
private int[] mCurPids;
private int[] mCurThreadPids;
@@ -285,10 +286,9 @@
public void update() {
if (DEBUG) Slog.v(TAG, "Update: " + this);
- mLastSampleTime = mCurrentSampleTime;
- mCurrentSampleTime = SystemClock.uptimeMillis();
- mLastSampleRealTime = mCurrentSampleRealTime;
- mCurrentSampleRealTime = SystemClock.elapsedRealtime();
+
+ final long nowUptime = SystemClock.uptimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
final long[] sysCpu = mSystemCpuData;
if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
@@ -304,30 +304,53 @@
final long irqtime = sysCpu[5];
final long softirqtime = sysCpu[6];
- mRelUserTime = (int)(usertime - mBaseUserTime);
- mRelSystemTime = (int)(systemtime - mBaseSystemTime);
- mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
- mRelIrqTime = (int)(irqtime - mBaseIrqTime);
- mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
- mRelIdleTime = (int)(idletime - mBaseIdleTime);
+ // This code is trying to avoid issues with idle time going backwards,
+ // but currently it gets into situations where it triggers most of the time. :(
+ if (true || (usertime >= mBaseUserTime && systemtime >= mBaseSystemTime
+ && iowaittime >= mBaseIoWaitTime && irqtime >= mBaseIrqTime
+ && softirqtime >= mBaseSoftIrqTime && idletime >= mBaseIdleTime)) {
+ mRelUserTime = (int)(usertime - mBaseUserTime);
+ mRelSystemTime = (int)(systemtime - mBaseSystemTime);
+ mRelIoWaitTime = (int)(iowaittime - mBaseIoWaitTime);
+ mRelIrqTime = (int)(irqtime - mBaseIrqTime);
+ mRelSoftIrqTime = (int)(softirqtime - mBaseSoftIrqTime);
+ mRelIdleTime = (int)(idletime - mBaseIdleTime);
+ mRelStatsAreGood = true;
- if (DEBUG) {
- Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
- + " S:" + sysCpu[2] + " I:" + sysCpu[3]
- + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
- + " O:" + sysCpu[6]);
- Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
- + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
+ if (DEBUG) {
+ Slog.i("Load", "Total U:" + sysCpu[0] + " N:" + sysCpu[1]
+ + " S:" + sysCpu[2] + " I:" + sysCpu[3]
+ + " W:" + sysCpu[4] + " Q:" + sysCpu[5]
+ + " O:" + sysCpu[6]);
+ Slog.i("Load", "Rel U:" + mRelUserTime + " S:" + mRelSystemTime
+ + " I:" + mRelIdleTime + " Q:" + mRelIrqTime);
+ }
+
+ mBaseUserTime = usertime;
+ mBaseSystemTime = systemtime;
+ mBaseIoWaitTime = iowaittime;
+ mBaseIrqTime = irqtime;
+ mBaseSoftIrqTime = softirqtime;
+ mBaseIdleTime = idletime;
+
+ } else {
+ mRelUserTime = 0;
+ mRelSystemTime = 0;
+ mRelIoWaitTime = 0;
+ mRelIrqTime = 0;
+ mRelSoftIrqTime = 0;
+ mRelIdleTime = 0;
+ mRelStatsAreGood = false;
+ Slog.w(TAG, "/proc/stats has gone backwards; skipping CPU update");
+ return;
}
-
- mBaseUserTime = usertime;
- mBaseSystemTime = systemtime;
- mBaseIoWaitTime = iowaittime;
- mBaseIrqTime = irqtime;
- mBaseSoftIrqTime = softirqtime;
- mBaseIdleTime = idletime;
}
+ mLastSampleTime = mCurrentSampleTime;
+ mCurrentSampleTime = nowUptime;
+ mLastSampleRealTime = mCurrentSampleRealTime;
+ mCurrentSampleRealTime = nowRealtime;
+
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
try {
mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
@@ -647,6 +670,10 @@
return mRelIdleTime;
}
+ final public boolean hasGoodLastStats() {
+ return mRelStatsAreGood;
+ }
+
final public float getTotalCpuPercent() {
int denom = mRelUserTime+mRelSystemTime+mRelIrqTime+mRelIdleTime;
if (denom <= 0) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 29ccb6a..2539a35 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -233,6 +233,7 @@
}
public static final void main(String[] argv) {
+ enableDdms();
if (argv.length == 2 && argv[1].equals("application")) {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application");
redirectLogStreams();
@@ -365,9 +366,9 @@
}
/**
- * Enable debugging features.
+ * Enable DDMS.
*/
- static {
+ static final void enableDdms() {
// Register handlers for DDM messages.
android.ddm.DdmRegister.registerHandlers();
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index c9b44be..a55fe9a 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -399,7 +399,7 @@
throws IllegalArgumentException {
int curArg = 0;
- boolean seenRuntimeArgs = true;
+ boolean seenRuntimeArgs = false;
for ( /* curArg */ ; curArg < args.length; curArg++) {
String arg = args[curArg];
@@ -533,14 +533,18 @@
}
}
- if (!seenRuntimeArgs) {
- throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
+ if (abiListQuery) {
+ if (args.length - curArg > 0) {
+ throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
+ }
+ } else {
+ if (!seenRuntimeArgs) {
+ throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
+ }
+
+ remainingArgs = new String[args.length - curArg];
+ System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);
}
-
- remainingArgs = new String[args.length - curArg];
-
- System.arraycopy(args, curArg, remainingArgs, 0,
- remainingArgs.length);
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 8107985..400ea37 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -355,7 +355,7 @@
Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
}
if (id != 0) {
- if (mResources.getColorStateList(id) == null) {
+ if (mResources.getColorStateList(id, null) == null) {
throw new IllegalArgumentException(
"Unable to find preloaded color resource #0x"
+ Integer.toHexString(id)
@@ -504,8 +504,8 @@
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
- "--runtime-init",
"--nice-name=system_server",
+ "--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
@@ -557,6 +557,7 @@
public static void main(String argv[]) {
try {
+ RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index a3c0db4..2b0d244 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -1,19 +1,19 @@
/**
* 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
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.statusbar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -43,5 +43,26 @@
void preloadRecentApps();
void cancelPreloadRecentApps();
void showScreenPinningRequest();
+
+ /**
+ * Notifies the status bar that an app transition is pending to delay applying some flags with
+ * visual impact until {@link #appTransitionReady} is called.
+ */
+ void appTransitionPending();
+
+ /**
+ * Notifies the status bar that a pending app transition has been cancelled.
+ */
+ void appTransitionCancelled();
+
+ /**
+ * Notifies the status bar that an app transition is now being executed.
+ *
+ * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
+ * status bar caused by this app transition in uptime millis
+ * @param statusBarAnimationsDuration the duration for all visual animations in the status
+ * bar caused by this app transition in millis
+ */
+ void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 40c009f..6cb839e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -1,16 +1,16 @@
/**
* 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
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
@@ -61,4 +61,25 @@
void toggleRecentApps();
void preloadRecentApps();
void cancelPreloadRecentApps();
+
+ /**
+ * Notifies the status bar that an app transition is pending to delay applying some flags with
+ * visual impact until {@link #appTransitionReady} is called.
+ */
+ void appTransitionPending();
+
+ /**
+ * Notifies the status bar that a pending app transition has been cancelled.
+ */
+ void appTransitionCancelled();
+
+ /**
+ * Notifies the status bar that an app transition is now being executed.
+ *
+ * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
+ * status bar caused by this app transition in uptime millis
+ * @param statusBarAnimationsDuration the duration for all visual animations in the status
+ * bar caused by this app transition in millis
+ */
+ void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 65b56ec..64e1d10 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -35,13 +35,14 @@
* trying to acquire, we use a short timeout to avoid deadlocks. The process
* is inelegant but this function is only used for debugging purposes.
*/
- public static void dumpAsync(Handler handler, final Dump dump, PrintWriter pw, long timeout) {
+ public static void dumpAsync(Handler handler, final Dump dump, PrintWriter pw,
+ final String prefix, long timeout) {
final StringWriter sw = new StringWriter();
if (handler.runWithScissors(new Runnable() {
@Override
public void run() {
PrintWriter lpw = new FastPrintWriter(sw);
- dump.dump(lpw);
+ dump.dump(lpw, prefix);
lpw.close();
}
}, timeout)) {
@@ -52,6 +53,6 @@
}
public interface Dump {
- void dump(PrintWriter pw);
+ void dump(PrintWriter pw, String prefix);
}
}
diff --git a/core/java/com/android/internal/view/ActionModeWrapper.java b/core/java/com/android/internal/view/ActionModeWrapper.java
new file mode 100644
index 0000000..72066b9
--- /dev/null
+++ b/core/java/com/android/internal/view/ActionModeWrapper.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.content.Context;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.android.internal.view.menu.MenuBuilder;
+
+/**
+ * ActionMode implementation that wraps several actions modes and creates them on the fly depending
+ * on the ActionMode type chosen by the client.
+ */
+public class ActionModeWrapper extends ActionMode {
+
+ /**
+ * Interface to defer the ActionMode creation until the type is chosen.
+ */
+ public interface ActionModeProvider {
+ /**
+ * Create the desired ActionMode, that will immediately be used as the current active mode
+ * in the decorator.
+ *
+ * @param callback The {@link ActionMode.Callback} to be used.
+ * @param menuBuilder The {@link MenuBuilder} that should be used by the created
+ * {@link ActionMode}. This will already have been populated.
+ * @return A new {@link ActionMode} ready to be used that uses menuBuilder as its menu.
+ */
+ ActionMode createActionMode(ActionMode.Callback callback, MenuBuilder menuBuilder);
+ }
+
+ private ActionMode mActionMode;
+ private final Context mContext;
+ private MenuBuilder mMenu;
+ private final ActionMode.Callback mCallback;
+ private boolean mTypeLocked = false;
+
+ private CharSequence mTitle;
+ private CharSequence mSubtitle;
+ private View mCustomView;
+
+ private final ActionModeProvider mActionModeProvider;
+
+ public ActionModeWrapper(
+ Context context, ActionMode.Callback callback, ActionModeProvider actionModeProvider) {
+ mContext = context;
+ mMenu = new MenuBuilder(context).setDefaultShowAsAction(
+ MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ mCallback = callback;
+ mActionModeProvider = actionModeProvider;
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ if (mActionMode != null) {
+ mActionMode.setTitle(title);
+ } else {
+ mTitle = title;
+ }
+ }
+
+ @Override
+ public void setTitle(int resId) {
+ if (mActionMode != null) {
+ mActionMode.setTitle(resId);
+ } else {
+ mTitle = resId != 0 ? mContext.getString(resId) : null;
+ }
+ }
+
+ @Override
+ public void setSubtitle(CharSequence subtitle) {
+ if (mActionMode != null) {
+ mActionMode.setSubtitle(subtitle);
+ } else {
+ mSubtitle = subtitle;
+ }
+ }
+
+ @Override
+ public void setSubtitle(int resId) {
+ if (mActionMode != null) {
+ mActionMode.setSubtitle(resId);
+ } else {
+ mSubtitle = resId != 0 ? mContext.getString(resId) : null;
+ }
+ }
+
+ @Override
+ public void setCustomView(View view) {
+ if (mActionMode != null) {
+ mActionMode.setCustomView(view);
+ } else {
+ mCustomView = view;
+ }
+ }
+
+ /**
+ * Set the current type as final and create the necessary ActionMode. After this call, any
+ * changes to the ActionMode type will be ignored.
+ */
+ public void lockType() {
+ mTypeLocked = true;
+ switch (getType()) {
+ case ActionMode.TYPE_PRIMARY:
+ default:
+ mActionMode = mActionModeProvider.createActionMode(mCallback, mMenu);
+ break;
+ case ActionMode.TYPE_FLOATING:
+ // Not implemented yet.
+ break;
+ }
+
+ if (mActionMode == null) {
+ return;
+ }
+
+ mActionMode.setTitle(mTitle);
+ mActionMode.setSubtitle(mSubtitle);
+ if (mCustomView != null) {
+ mActionMode.setCustomView(mCustomView);
+ }
+
+ mTitle = null;
+ mSubtitle = null;
+ mCustomView = null;
+ }
+
+ @Override
+ public void setType(int type) {
+ if (!mTypeLocked) {
+ super.setType(type);
+ } else {
+ throw new IllegalStateException(
+ "You can't change the ActionMode's type after onCreateActionMode.");
+ }
+ }
+
+ @Override
+ public void invalidate() {
+ if (mActionMode != null) {
+ mActionMode.invalidate();
+ }
+ }
+
+ @Override
+ public void finish() {
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mMenu;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ if (mActionMode != null) {
+ return mActionMode.getTitle();
+ }
+ return mTitle;
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ if (mActionMode != null) {
+ return mActionMode.getSubtitle();
+ }
+ return mSubtitle;
+ }
+
+ @Override
+ public View getCustomView() {
+ if (mActionMode != null) {
+ return mActionMode.getCustomView();
+ }
+ return mCustomView;
+ }
+
+ @Override
+ public MenuInflater getMenuInflater() {
+ return new MenuInflater(mContext);
+ }
+
+}
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index d5d3602..2812b77 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -20,6 +20,7 @@
import com.android.internal.view.menu.SubMenuBuilder;
import com.android.internal.widget.ActionBarContextView;
+import android.annotation.Nullable;
import android.content.Context;
import android.view.ActionMode;
import android.view.Menu;
@@ -41,13 +42,15 @@
private MenuBuilder mMenu;
public StandaloneActionMode(Context context, ActionBarContextView view,
- ActionMode.Callback callback, boolean isFocusable) {
+ ActionMode.Callback callback, boolean isFocusable, @Nullable MenuBuilder menuBuilder) {
mContext = context;
mContextView = view;
mCallback = callback;
- mMenu = new MenuBuilder(view.getContext()).setDefaultShowAsAction(
- MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ mMenu = (menuBuilder != null)
+ ? menuBuilder
+ : new MenuBuilder(view.getContext()).setDefaultShowAsAction(
+ MenuItem.SHOW_AS_ACTION_IF_ROOM);
mMenu.setCallback(this);
mFocusable = isFocusable;
}
@@ -64,12 +67,12 @@
@Override
public void setTitle(int resId) {
- setTitle(mContext.getString(resId));
+ setTitle(resId != 0 ? mContext.getString(resId) : null);
}
@Override
public void setSubtitle(int resId) {
- setSubtitle(mContext.getString(resId));
+ setSubtitle(resId != 0 ? mContext.getString(resId) : null);
}
@Override
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 5d3f464..ae5999a 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -158,7 +158,7 @@
removeView(mCustomView);
}
mCustomView = view;
- if (mTitleLayout != null) {
+ if (view != null && mTitleLayout != null) {
removeView(mTitleLayout);
mTitleLayout = null;
}
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
new file mode 100644
index 0000000..64e6c69
--- /dev/null
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.internal.R;
+
+/**
+ * An extension of LinearLayout that automatically switches to vertical
+ * orientation when it can't fit its child views horizontally.
+ */
+public class ButtonBarLayout extends LinearLayout {
+ /** Spacer used in horizontal orientation. */
+ private final View mSpacer;
+
+ /** Whether the current configuration allows stacking. */
+ private final boolean mAllowStacked;
+
+ /** Whether the layout is currently stacked. */
+ private boolean mStacked;
+
+ public ButtonBarLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mAllowStacked = context.getResources().getBoolean(R.bool.allow_stacked_button_bar);
+ mSpacer = findViewById(R.id.spacer);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ // Maybe we can fit the content now?
+ if (w > oldw && mStacked) {
+ setStacked(false);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ if (mAllowStacked && getOrientation() == LinearLayout.HORIZONTAL) {
+ final int measuredWidth = getMeasuredWidthAndState();
+ final int measuredWidthState = measuredWidth & MEASURED_STATE_MASK;
+ if (measuredWidthState == MEASURED_STATE_TOO_SMALL) {
+ setStacked(true);
+
+ // Measure again in the new orientation.
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+ }
+
+ private void setStacked(boolean stacked) {
+ setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
+ setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
+
+ if (mSpacer != null) {
+ mSpacer.setVisibility(stacked ? View.GONE : View.INVISIBLE);
+ }
+
+ // Reverse the child order. This is specific to the Material button
+ // bar's layout XML and will probably not generalize.
+ final int childCount = getChildCount();
+ for (int i = childCount - 2; i >= 0; i--) {
+ bringChildToFront(getChildAt(i));
+ }
+
+ mStacked = stacked;
+ }
+}
diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
index 0e046cb..bdf17fc 100644
--- a/core/java/com/android/internal/widget/ExploreByTouchHelper.java
+++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
@@ -567,7 +567,15 @@
}
// TODO: Check virtual view visibility.
if (!isAccessibilityFocused(virtualViewId)) {
+ // Clear focus from the previously focused view, if applicable.
+ if (mFocusedVirtualViewId != INVALID_ID) {
+ sendEventForVirtualView(mFocusedVirtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ }
+
+ // Set focus on the new view.
mFocusedVirtualViewId = virtualViewId;
+
// TODO: Only invalidate virtual view bounds.
mView.invalidate();
sendEventForVirtualView(virtualViewId,
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index d617c05..89990c2 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -19,6 +19,7 @@
import android.animation.TimeInterpolator;
import android.app.Activity;
import android.content.Context;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -38,6 +39,7 @@
private static final String TAG = "SwipeDismissLayout";
private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .33f;
+ private boolean mUseDynamicTranslucency = true;
public interface OnDismissedListener {
void onDismissed(SwipeDismissLayout layout);
@@ -85,7 +87,7 @@
// and temporarily disables translucency when it is fully visible.
// As soon as the user starts swiping, we will re-enable
// translucency.
- if (getContext() instanceof Activity) {
+ if (mUseDynamicTranslucency && getContext() instanceof Activity) {
((Activity) getContext()).convertFromTranslucent();
}
}
@@ -117,6 +119,11 @@
android.R.integer.config_shortAnimTime);
mCancelInterpolator = new DecelerateInterpolator(1.5f);
mDismissInterpolator = new AccelerateInterpolator(1.5f);
+ TypedArray a = context.getTheme().obtainStyledAttributes(
+ com.android.internal.R.styleable.Theme);
+ mUseDynamicTranslucency = !a.hasValue(
+ com.android.internal.R.styleable.Window_windowIsTranslucent);
+ a.recycle();
}
public void setOnDismissedListener(OnDismissedListener listener) {
@@ -230,7 +237,7 @@
mLastX = ev.getRawX();
updateSwiping(ev);
if (mSwiping) {
- if (getContext() instanceof Activity) {
+ if (mUseDynamicTranslucency && getContext() instanceof Activity) {
((Activity) getContext()).convertToTranslucent(null, null);
}
setProgress(ev.getRawX() - mDownX);
@@ -254,7 +261,7 @@
}
protected void cancel() {
- if (getContext() instanceof Activity) {
+ if (mUseDynamicTranslucency && getContext() instanceof Activity) {
((Activity) getContext()).convertFromTranslucent();
}
if (mProgressListener != null) {
diff --git a/core/java/org/apache/http/conn/ConnectTimeoutException.java b/core/java/org/apache/http/conn/ConnectTimeoutException.java
new file mode 100644
index 0000000..6cc6922
--- /dev/null
+++ b/core/java/org/apache/http/conn/ConnectTimeoutException.java
@@ -0,0 +1,69 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ConnectTimeoutException.java $
+ * $Revision: 617645 $
+ * $Date: 2008-02-01 13:05:31 -0800 (Fri, 01 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn;
+
+import java.io.InterruptedIOException;
+
+/**
+ * A timeout while connecting to an HTTP server or waiting for an
+ * available connection from an HttpConnectionManager.
+ *
+ * @author <a href="mailto:laura@lwerner.org">Laura Werner</a>
+ *
+ * @since 4.0
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public class ConnectTimeoutException extends InterruptedIOException {
+
+ private static final long serialVersionUID = -4816682903149535989L;
+
+ /**
+ * Creates a ConnectTimeoutException with a <tt>null</tt> detail message.
+ */
+ public ConnectTimeoutException() {
+ super();
+ }
+
+ /**
+ * Creates a ConnectTimeoutException with the specified detail message.
+ *
+ * @param message The exception detail message
+ */
+ public ConnectTimeoutException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/core/java/org/apache/http/conn/scheme/HostNameResolver.java b/core/java/org/apache/http/conn/scheme/HostNameResolver.java
new file mode 100644
index 0000000..30ef298
--- /dev/null
+++ b/core/java/org/apache/http/conn/scheme/HostNameResolver.java
@@ -0,0 +1,47 @@
+/*
+ * $HeadURL:$
+ * $Revision:$
+ * $Date:$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface HostNameResolver {
+
+ InetAddress resolve (String hostname) throws IOException;
+
+}
diff --git a/core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java b/core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java
new file mode 100644
index 0000000..b9f53489
--- /dev/null
+++ b/core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java
@@ -0,0 +1,77 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/scheme/LayeredSocketFactory.java $
+ * $Revision: 645850 $
+ * $Date: 2008-04-08 04:08:52 -0700 (Tue, 08 Apr 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.scheme;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * A {@link SocketFactory SocketFactory} for layered sockets (SSL/TLS).
+ * See there for things to consider when implementing a socket factory.
+ *
+ * @author Michael Becke
+ * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ * @since 4.0
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface LayeredSocketFactory extends SocketFactory {
+
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param host the host name/IP
+ * @param port the port on the host
+ * @param autoClose a flag for closing the underling socket when the created
+ * socket is closed
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ * @throws UnknownHostException if the IP address of the host cannot be
+ * determined
+ */
+ Socket createSocket(
+ Socket socket,
+ String host,
+ int port,
+ boolean autoClose
+ ) throws IOException, UnknownHostException;
+
+}
diff --git a/core/java/org/apache/http/conn/scheme/SocketFactory.java b/core/java/org/apache/http/conn/scheme/SocketFactory.java
new file mode 100644
index 0000000..c6bc03c7
--- /dev/null
+++ b/core/java/org/apache/http/conn/scheme/SocketFactory.java
@@ -0,0 +1,143 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/scheme/SocketFactory.java $
+ * $Revision: 645850 $
+ * $Date: 2008-04-08 04:08:52 -0700 (Tue, 08 Apr 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.scheme;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.params.HttpParams;
+
+/**
+ * A factory for creating and connecting sockets.
+ * The factory encapsulates the logic for establishing a socket connection.
+ * <br/>
+ * Both {@link java.lang.Object#equals(java.lang.Object) Object.equals()}
+ * and {@link java.lang.Object#hashCode() Object.hashCode()}
+ * must be overridden for the correct operation of some connection managers.
+ *
+ * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
+ * @author Michael Becke
+ * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface SocketFactory {
+
+ /**
+ * Creates a new, unconnected socket.
+ * The socket should subsequently be passed to
+ * {@link #connectSocket connectSocket}.
+ *
+ * @return a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ */
+ Socket createSocket()
+ throws IOException
+ ;
+
+
+ /**
+ * Connects a socket to the given host.
+ *
+ * @param sock the socket to connect, as obtained from
+ * {@link #createSocket createSocket}.
+ * <code>null</code> indicates that a new socket
+ * should be created and connected.
+ * @param host the host to connect to
+ * @param port the port to connect to on the host
+ * @param localAddress the local address to bind the socket to, or
+ * <code>null</code> for any
+ * @param localPort the port on the local machine,
+ * 0 or a negative number for any
+ * @param params additional {@link HttpParams parameters} for connecting
+ *
+ * @return the connected socket. The returned object may be different
+ * from the <code>sock</code> argument if this factory supports
+ * a layered protocol.
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws UnknownHostException if the IP address of the target host
+ * can not be determined
+ * @throws ConnectTimeoutException if the socket cannot be connected
+ * within the time limit defined in the <code>params</code>
+ */
+ Socket connectSocket(
+ Socket sock,
+ String host,
+ int port,
+ InetAddress localAddress,
+ int localPort,
+ HttpParams params
+ ) throws IOException, UnknownHostException, ConnectTimeoutException;
+
+
+ /**
+ * Checks whether a socket provides a secure connection.
+ * The socket must be {@link #connectSocket connected}
+ * by this factory.
+ * The factory will <i>not</i> perform I/O operations
+ * in this method.
+ * <br/>
+ * As a rule of thumb, plain sockets are not secure and
+ * TLS/SSL sockets are secure. However, there may be
+ * application specific deviations. For example, a plain
+ * socket to a host in the same intranet ("trusted zone")
+ * could be considered secure. On the other hand, a
+ * TLS/SSL socket could be considered insecure based on
+ * the cypher suite chosen for the connection.
+ *
+ * @param sock the connected socket to check
+ *
+ * @return <code>true</code> if the connection of the socket
+ * should be considered secure, or
+ * <code>false</code> if it should not
+ *
+ * @throws IllegalArgumentException
+ * if the argument is invalid, for example because it is
+ * not a connected socket or was created by a different
+ * socket factory.
+ * Note that socket factories are <i>not</i> required to
+ * check these conditions, they may simply return a default
+ * value when called with an invalid socket argument.
+ */
+ boolean isSecure(Socket sock)
+ throws IllegalArgumentException
+ ;
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/AbstractVerifier.java b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
new file mode 100644
index 0000000..e264f1c4
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/AbstractVerifier.java
@@ -0,0 +1,288 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java $
+ * $Revision: 653041 $
+ * $Date: 2008-05-03 03:39:28 -0700 (Sat, 03 May 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+import java.util.regex.Pattern;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.net.ssl.DistinguishedNameParser;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+/**
+ * Abstract base class for all standard {@link X509HostnameVerifier}
+ * implementations.
+ *
+ * @author Julius Davies
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public abstract class AbstractVerifier implements X509HostnameVerifier {
+
+ private static final Pattern IPV4_PATTERN = Pattern.compile(
+ "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
+
+ /**
+ * This contains a list of 2nd-level domains that aren't allowed to
+ * have wildcards when combined with country-codes.
+ * For example: [*.co.uk].
+ * <p/>
+ * The [*.co.uk] problem is an interesting one. Should we just hope
+ * that CA's would never foolishly allow such a certificate to happen?
+ * Looks like we're the only implementation guarding against this.
+ * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
+ */
+ private final static String[] BAD_COUNTRY_2LDS =
+ { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
+ "lg", "ne", "net", "or", "org" };
+
+ static {
+ // Just in case developer forgot to manually sort the array. :-)
+ Arrays.sort(BAD_COUNTRY_2LDS);
+ }
+
+ public AbstractVerifier() {
+ super();
+ }
+
+ public final void verify(String host, SSLSocket ssl)
+ throws IOException {
+ if(host == null) {
+ throw new NullPointerException("host to verify is null");
+ }
+
+ SSLSession session = ssl.getSession();
+ Certificate[] certs = session.getPeerCertificates();
+ X509Certificate x509 = (X509Certificate) certs[0];
+ verify(host, x509);
+ }
+
+ public final boolean verify(String host, SSLSession session) {
+ try {
+ Certificate[] certs = session.getPeerCertificates();
+ X509Certificate x509 = (X509Certificate) certs[0];
+ verify(host, x509);
+ return true;
+ }
+ catch(SSLException e) {
+ return false;
+ }
+ }
+
+ public final void verify(String host, X509Certificate cert)
+ throws SSLException {
+ String[] cns = getCNs(cert);
+ String[] subjectAlts = getDNSSubjectAlts(cert);
+ verify(host, cns, subjectAlts);
+ }
+
+ public final void verify(final String host, final String[] cns,
+ final String[] subjectAlts,
+ final boolean strictWithSubDomains)
+ throws SSLException {
+
+ // Build the list of names we're going to check. Our DEFAULT and
+ // STRICT implementations of the HostnameVerifier only use the
+ // first CN provided. All other CNs are ignored.
+ // (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
+ LinkedList<String> names = new LinkedList<String>();
+ if(cns != null && cns.length > 0 && cns[0] != null) {
+ names.add(cns[0]);
+ }
+ if(subjectAlts != null) {
+ for (String subjectAlt : subjectAlts) {
+ if (subjectAlt != null) {
+ names.add(subjectAlt);
+ }
+ }
+ }
+
+ if(names.isEmpty()) {
+ String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
+ throw new SSLException(msg);
+ }
+
+ // StringBuffer for building the error message.
+ StringBuffer buf = new StringBuffer();
+
+ // We're can be case-insensitive when comparing the host we used to
+ // establish the socket to the hostname in the certificate.
+ String hostName = host.trim().toLowerCase(Locale.ENGLISH);
+ boolean match = false;
+ for(Iterator<String> it = names.iterator(); it.hasNext();) {
+ // Don't trim the CN, though!
+ String cn = it.next();
+ cn = cn.toLowerCase(Locale.ENGLISH);
+ // Store CN in StringBuffer in case we need to report an error.
+ buf.append(" <");
+ buf.append(cn);
+ buf.append('>');
+ if(it.hasNext()) {
+ buf.append(" OR");
+ }
+
+ // The CN better have at least two dots if it wants wildcard
+ // action. It also can't be [*.co.uk] or [*.co.jp] or
+ // [*.org.uk], etc...
+ boolean doWildcard = cn.startsWith("*.") &&
+ cn.indexOf('.', 2) != -1 &&
+ acceptableCountryWildcard(cn) &&
+ !isIPv4Address(host);
+
+ if(doWildcard) {
+ match = hostName.endsWith(cn.substring(1));
+ if(match && strictWithSubDomains) {
+ // If we're in strict mode, then [*.foo.com] is not
+ // allowed to match [a.b.foo.com]
+ match = countDots(hostName) == countDots(cn);
+ }
+ } else {
+ match = hostName.equals(cn);
+ }
+ if(match) {
+ break;
+ }
+ }
+ if(!match) {
+ throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
+ }
+ }
+
+ public static boolean acceptableCountryWildcard(String cn) {
+ int cnLen = cn.length();
+ if(cnLen >= 7 && cnLen <= 9) {
+ // Look for the '.' in the 3rd-last position:
+ if(cn.charAt(cnLen - 3) == '.') {
+ // Trim off the [*.] and the [.XX].
+ String s = cn.substring(2, cnLen - 3);
+ // And test against the sorted array of bad 2lds:
+ int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
+ return x < 0;
+ }
+ }
+ return true;
+ }
+
+ public static String[] getCNs(X509Certificate cert) {
+ DistinguishedNameParser dnParser =
+ new DistinguishedNameParser(cert.getSubjectX500Principal());
+ List<String> cnList = dnParser.getAllMostSpecificFirst("cn");
+
+ if(!cnList.isEmpty()) {
+ String[] cns = new String[cnList.size()];
+ cnList.toArray(cns);
+ return cns;
+ } else {
+ return null;
+ }
+ }
+
+
+ /**
+ * Extracts the array of SubjectAlt DNS names from an X509Certificate.
+ * Returns null if there aren't any.
+ * <p/>
+ * Note: Java doesn't appear able to extract international characters
+ * from the SubjectAlts. It can only extract international characters
+ * from the CN field.
+ * <p/>
+ * (Or maybe the version of OpenSSL I'm using to test isn't storing the
+ * international characters correctly in the SubjectAlts?).
+ *
+ * @param cert X509Certificate
+ * @return Array of SubjectALT DNS names stored in the certificate.
+ */
+ public static String[] getDNSSubjectAlts(X509Certificate cert) {
+ LinkedList<String> subjectAltList = new LinkedList<String>();
+ Collection<List<?>> c = null;
+ try {
+ c = cert.getSubjectAlternativeNames();
+ }
+ catch(CertificateParsingException cpe) {
+ Logger.getLogger(AbstractVerifier.class.getName())
+ .log(Level.FINE, "Error parsing certificate.", cpe);
+ }
+ if(c != null) {
+ for (List<?> aC : c) {
+ List<?> list = aC;
+ int type = ((Integer) list.get(0)).intValue();
+ // If type is 2, then we've got a dNSName
+ if (type == 2) {
+ String s = (String) list.get(1);
+ subjectAltList.add(s);
+ }
+ }
+ }
+ if(!subjectAltList.isEmpty()) {
+ String[] subjectAlts = new String[subjectAltList.size()];
+ subjectAltList.toArray(subjectAlts);
+ return subjectAlts;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Counts the number of dots "." in a string.
+ * @param s string to count dots from
+ * @return number of dots
+ */
+ public static int countDots(final String s) {
+ int count = 0;
+ for(int i = 0; i < s.length(); i++) {
+ if(s.charAt(i) == '.') {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private static boolean isIPv4Address(final String input) {
+ return IPV4_PATTERN.matcher(input).matches();
+ }
+}
diff --git a/core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java b/core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java
new file mode 100644
index 0000000..c2bf4c4
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java
@@ -0,0 +1,59 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java $
+ * $Revision: 617642 $
+ * $Date: 2008-02-01 12:54:07 -0800 (Fri, 01 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+/**
+ * The ALLOW_ALL HostnameVerifier essentially turns hostname verification
+ * off. This implementation is a no-op, and never throws the SSLException.
+ *
+ * @author Julius Davies
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public class AllowAllHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) {
+ // Allow everything - so never blowup.
+ }
+
+ @Override
+ public final String toString() {
+ return "ALLOW_ALL";
+ }
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java b/core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java
new file mode 100644
index 0000000..48a7bf9
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java
@@ -0,0 +1,67 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java $
+ * $Revision: 617642 $
+ * $Date: 2008-02-01 12:54:07 -0800 (Fri, 01 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+import javax.net.ssl.SSLException;
+
+/**
+ * The HostnameVerifier that works the same way as Curl and Firefox.
+ * <p/>
+ * The hostname must match either the first CN, or any of the subject-alts.
+ * A wildcard can occur in the CN, and in any of the subject-alts.
+ * <p/>
+ * The only difference between BROWSER_COMPATIBLE and STRICT is that a wildcard
+ * (such as "*.foo.com") with BROWSER_COMPATIBLE matches all subdomains,
+ * including "a.b.foo.com".
+ *
+ * @author Julius Davies
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public class BrowserCompatHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) throws SSLException {
+ verify(host, cns, subjectAlts, false);
+ }
+
+ @Override
+ public final String toString() {
+ return "BROWSER_COMPATIBLE";
+ }
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
new file mode 100644
index 0000000..4d53d40
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/SSLSocketFactory.java
@@ -0,0 +1,408 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java $
+ * $Revision: 659194 $
+ * $Date: 2008-05-22 11:33:47 -0700 (Thu, 22 May 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+import org.apache.http.conn.scheme.HostNameResolver;
+import org.apache.http.conn.scheme.LayeredSocketFactory;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+/**
+ * Layered socket factory for TLS/SSL connections, based on JSSE.
+ *.
+ * <p>
+ * SSLSocketFactory can be used to validate the identity of the HTTPS
+ * server against a list of trusted certificates and to authenticate to
+ * the HTTPS server using a private key.
+ * </p>
+ *
+ * <p>
+ * SSLSocketFactory will enable server authentication when supplied with
+ * a {@link KeyStore truststore} file containg one or several trusted
+ * certificates. The client secure socket will reject the connection during
+ * the SSL session handshake if the target HTTPS server attempts to
+ * authenticate itself with a non-trusted certificate.
+ * </p>
+ *
+ * <p>
+ * Use JDK keytool utility to import a trusted certificate and generate a truststore file:
+ * <pre>
+ * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore
+ * </pre>
+ * </p>
+ *
+ * <p>
+ * SSLSocketFactory will enable client authentication when supplied with
+ * a {@link KeyStore keystore} file containg a private key/public certificate
+ * pair. The client secure socket will use the private key to authenticate
+ * itself to the target HTTPS server during the SSL session handshake if
+ * requested to do so by the server.
+ * The target HTTPS server will in its turn verify the certificate presented
+ * by the client in order to establish client's authenticity
+ * </p>
+ *
+ * <p>
+ * Use the following sequence of actions to generate a keystore file
+ * </p>
+ * <ul>
+ * <li>
+ * <p>
+ * Use JDK keytool utility to generate a new key
+ * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre>
+ * For simplicity use the same password for the key as that of the keystore
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Issue a certificate signing request (CSR)
+ * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Send the certificate request to the trusted Certificate Authority for signature.
+ * One may choose to act as her own CA and sign the certificate request using a PKI
+ * tool, such as OpenSSL.
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the trusted CA root certificate
+ * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Import the PKCS#7 file containg the complete certificate chain
+ * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * <li>
+ * <p>
+ * Verify the content the resultant keystore file
+ * <pre>keytool -list -v -keystore my.keystore</pre>
+ * </p>
+ * </li>
+ * </ul>
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ * @author Julius Davies
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public class SSLSocketFactory implements LayeredSocketFactory {
+
+ public static final String TLS = "TLS";
+ public static final String SSL = "SSL";
+ public static final String SSLV2 = "SSLv2";
+
+ public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER
+ = new AllowAllHostnameVerifier();
+
+ public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
+ = new BrowserCompatHostnameVerifier();
+
+ public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER
+ = new StrictHostnameVerifier();
+
+ /*
+ * Put defaults into holder class to avoid class preloading creating an
+ * instance of the classes referenced.
+ */
+ private static class NoPreloadHolder {
+ /**
+ * The factory using the default JVM settings for secure connections.
+ */
+ private static final SSLSocketFactory DEFAULT_FACTORY = new SSLSocketFactory();
+ }
+
+ /**
+ * Gets an singleton instance of the SSLProtocolSocketFactory.
+ * @return a SSLProtocolSocketFactory
+ */
+ public static SSLSocketFactory getSocketFactory() {
+ return NoPreloadHolder.DEFAULT_FACTORY;
+ }
+
+ private final SSLContext sslcontext;
+ private final javax.net.ssl.SSLSocketFactory socketfactory;
+ private final HostNameResolver nameResolver;
+ private X509HostnameVerifier hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+
+ public SSLSocketFactory(
+ String algorithm,
+ final KeyStore keystore,
+ final String keystorePassword,
+ final KeyStore truststore,
+ final SecureRandom random,
+ final HostNameResolver nameResolver)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
+ {
+ super();
+ if (algorithm == null) {
+ algorithm = TLS;
+ }
+ KeyManager[] keymanagers = null;
+ if (keystore != null) {
+ keymanagers = createKeyManagers(keystore, keystorePassword);
+ }
+ TrustManager[] trustmanagers = null;
+ if (truststore != null) {
+ trustmanagers = createTrustManagers(truststore);
+ }
+ this.sslcontext = SSLContext.getInstance(algorithm);
+ this.sslcontext.init(keymanagers, trustmanagers, random);
+ this.socketfactory = this.sslcontext.getSocketFactory();
+ this.nameResolver = nameResolver;
+ }
+
+ public SSLSocketFactory(
+ final KeyStore keystore,
+ final String keystorePassword,
+ final KeyStore truststore)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
+ {
+ this(TLS, keystore, keystorePassword, truststore, null, null);
+ }
+
+ public SSLSocketFactory(final KeyStore keystore, final String keystorePassword)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
+ {
+ this(TLS, keystore, keystorePassword, null, null, null);
+ }
+
+ public SSLSocketFactory(final KeyStore truststore)
+ throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException
+ {
+ this(TLS, null, null, truststore, null, null);
+ }
+
+ /**
+ * Constructs an HttpClient SSLSocketFactory backed by the given JSSE
+ * SSLSocketFactory.
+ *
+ * @hide
+ */
+ public SSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory) {
+ super();
+ this.sslcontext = null;
+ this.socketfactory = socketfactory;
+ this.nameResolver = null;
+ }
+
+ /**
+ * Creates the default SSL socket factory.
+ * This constructor is used exclusively to instantiate the factory for
+ * {@link #getSocketFactory getSocketFactory}.
+ */
+ private SSLSocketFactory() {
+ super();
+ this.sslcontext = null;
+ this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
+ this.nameResolver = null;
+ }
+
+ private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password)
+ throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
+ if (keystore == null) {
+ throw new IllegalArgumentException("Keystore may not be null");
+ }
+ KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
+ KeyManagerFactory.getDefaultAlgorithm());
+ kmfactory.init(keystore, password != null ? password.toCharArray(): null);
+ return kmfactory.getKeyManagers();
+ }
+
+ private static TrustManager[] createTrustManagers(final KeyStore keystore)
+ throws KeyStoreException, NoSuchAlgorithmException {
+ if (keystore == null) {
+ throw new IllegalArgumentException("Keystore may not be null");
+ }
+ TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(
+ TrustManagerFactory.getDefaultAlgorithm());
+ tmfactory.init(keystore);
+ return tmfactory.getTrustManagers();
+ }
+
+
+ // non-javadoc, see interface org.apache.http.conn.SocketFactory
+ public Socket createSocket()
+ throws IOException {
+
+ // the cast makes sure that the factory is working as expected
+ return (SSLSocket) this.socketfactory.createSocket();
+ }
+
+
+ // non-javadoc, see interface org.apache.http.conn.SocketFactory
+ public Socket connectSocket(
+ final Socket sock,
+ final String host,
+ final int port,
+ final InetAddress localAddress,
+ int localPort,
+ final HttpParams params
+ ) throws IOException {
+
+ if (host == null) {
+ throw new IllegalArgumentException("Target host may not be null.");
+ }
+ if (params == null) {
+ throw new IllegalArgumentException("Parameters may not be null.");
+ }
+
+ SSLSocket sslsock = (SSLSocket)
+ ((sock != null) ? sock : createSocket());
+
+ if ((localAddress != null) || (localPort > 0)) {
+
+ // we need to bind explicitly
+ if (localPort < 0)
+ localPort = 0; // indicates "any"
+
+ InetSocketAddress isa =
+ new InetSocketAddress(localAddress, localPort);
+ sslsock.bind(isa);
+ }
+
+ int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
+ int soTimeout = HttpConnectionParams.getSoTimeout(params);
+
+ InetSocketAddress remoteAddress;
+ if (this.nameResolver != null) {
+ remoteAddress = new InetSocketAddress(this.nameResolver.resolve(host), port);
+ } else {
+ remoteAddress = new InetSocketAddress(host, port);
+ }
+
+ sslsock.connect(remoteAddress, connTimeout);
+
+ sslsock.setSoTimeout(soTimeout);
+ try {
+ hostnameVerifier.verify(host, sslsock);
+ // verifyHostName() didn't blowup - good!
+ } catch (IOException iox) {
+ // close the socket before re-throwing the exception
+ try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
+ throw iox;
+ }
+
+ return sslsock;
+ }
+
+
+ /**
+ * Checks whether a socket connection is secure.
+ * This factory creates TLS/SSL socket connections
+ * which, by default, are considered secure.
+ * <br/>
+ * Derived classes may override this method to perform
+ * runtime checks, for example based on the cypher suite.
+ *
+ * @param sock the connected socket
+ *
+ * @return <code>true</code>
+ *
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public boolean isSecure(Socket sock)
+ throws IllegalArgumentException {
+
+ if (sock == null) {
+ throw new IllegalArgumentException("Socket may not be null.");
+ }
+ // This instanceof check is in line with createSocket() above.
+ if (!(sock instanceof SSLSocket)) {
+ throw new IllegalArgumentException
+ ("Socket not created by this factory.");
+ }
+ // This check is performed last since it calls the argument object.
+ if (sock.isClosed()) {
+ throw new IllegalArgumentException("Socket is closed.");
+ }
+
+ return true;
+
+ } // isSecure
+
+
+ // non-javadoc, see interface LayeredSocketFactory
+ public Socket createSocket(
+ final Socket socket,
+ final String host,
+ final int port,
+ final boolean autoClose
+ ) throws IOException, UnknownHostException {
+ SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
+ socket,
+ host,
+ port,
+ autoClose
+ );
+ hostnameVerifier.verify(host, sslSocket);
+ // verifyHostName() didn't blowup - good!
+ return sslSocket;
+ }
+
+ public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
+ if ( hostnameVerifier == null ) {
+ throw new IllegalArgumentException("Hostname verifier may not be null");
+ }
+ this.hostnameVerifier = hostnameVerifier;
+ }
+
+ public X509HostnameVerifier getHostnameVerifier() {
+ return hostnameVerifier;
+ }
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java b/core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java
new file mode 100644
index 0000000..bd9e70d
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java
@@ -0,0 +1,74 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java $
+ * $Revision: 617642 $
+ * $Date: 2008-02-01 12:54:07 -0800 (Fri, 01 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+import javax.net.ssl.SSLException;
+
+/**
+ * The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun
+ * Java 5, Sun Java 6-rc. It's also pretty close to IE6. This
+ * implementation appears to be compliant with RFC 2818 for dealing with
+ * wildcards.
+ * <p/>
+ * The hostname must match either the first CN, or any of the subject-alts.
+ * A wildcard can occur in the CN, and in any of the subject-alts. The
+ * one divergence from IE6 is how we only check the first CN. IE6 allows
+ * a match against any of the CNs present. We decided to follow in
+ * Sun Java 1.4's footsteps and only check the first CN. (If you need
+ * to check all the CN's, feel free to write your own implementation!).
+ * <p/>
+ * A wildcard such as "*.foo.com" matches only subdomains in the same
+ * level, for example "a.foo.com". It does not match deeper subdomains
+ * such as "a.b.foo.com".
+ *
+ * @author Julius Davies
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public class StrictHostnameVerifier extends AbstractVerifier {
+
+ public final void verify(
+ final String host,
+ final String[] cns,
+ final String[] subjectAlts) throws SSLException {
+ verify(host, cns, subjectAlts, true);
+ }
+
+ @Override
+ public final String toString() {
+ return "STRICT";
+ }
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java b/core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java
new file mode 100644
index 0000000..e38db5f
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java
@@ -0,0 +1,91 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/X509HostnameVerifier.java $
+ * $Revision: 618365 $
+ * $Date: 2008-02-04 10:20:08 -0800 (Mon, 04 Feb 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn.ssl;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+
+/**
+ * Interface for checking if a hostname matches the names stored inside the
+ * server's X.509 certificate. Implements javax.net.ssl.HostnameVerifier, but
+ * we don't actually use that interface. Instead we added some methods that
+ * take String parameters (instead of javax.net.ssl.HostnameVerifier's
+ * SSLSession). JUnit is a lot easier this way! :-)
+ * <p/>
+ * We provide the HostnameVerifier.DEFAULT, HostnameVerifier.STRICT, and
+ * HostnameVerifier.ALLOW_ALL implementations. But feel free to define
+ * your own implementation!
+ * <p/>
+ * Inspired by Sebastian Hauer's original StrictSSLProtocolSocketFactory in the
+ * HttpClient "contrib" repository.
+ *
+ * @author Julius Davies
+ * @author <a href="mailto:hauer@psicode.com">Sebastian Hauer</a>
+ *
+ * @since 4.0 (8-Dec-2006)
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface X509HostnameVerifier extends HostnameVerifier {
+
+ boolean verify(String host, SSLSession session);
+
+ void verify(String host, SSLSocket ssl) throws IOException;
+
+ void verify(String host, X509Certificate cert) throws SSLException;
+
+ /**
+ * Checks to see if the supplied hostname matches any of the supplied CNs
+ * or "DNS" Subject-Alts. Most implementations only look at the first CN,
+ * and ignore any additional CNs. Most implementations do look at all of
+ * the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
+ * according to RFC 2818.
+ *
+ * @param cns CN fields, in order, as extracted from the X.509
+ * certificate.
+ * @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
+ * from the X.509 certificate.
+ * @param host The hostname to verify.
+ * @throws SSLException If verification failed.
+ */
+ void verify(String host, String[] cns, String[] subjectAlts)
+ throws SSLException;
+
+
+}
diff --git a/core/java/org/apache/http/conn/ssl/package.html b/core/java/org/apache/http/conn/ssl/package.html
new file mode 100644
index 0000000..a5c737f
--- /dev/null
+++ b/core/java/org/apache/http/conn/ssl/package.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+<!--
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/conn/ssl/package.html $
+ * $Revision: 555193 $
+ * $Date: 2007-07-11 00:36:47 -0700 (Wed, 11 Jul 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+-->
+</head>
+<body>
+TLS/SSL specific parts of the <i>HttpConn</i> API.
+
+</body>
+</html>
diff --git a/core/java/org/apache/http/params/CoreConnectionPNames.java b/core/java/org/apache/http/params/CoreConnectionPNames.java
new file mode 100644
index 0000000..9479db1
--- /dev/null
+++ b/core/java/org/apache/http/params/CoreConnectionPNames.java
@@ -0,0 +1,136 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/params/CoreConnectionPNames.java $
+ * $Revision: 576077 $
+ * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.params;
+
+
+/**
+ * Defines parameter names for connections in HttpCore.
+ *
+ * @version $Revision: 576077 $
+ *
+ * @since 4.0
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface CoreConnectionPNames {
+
+ /**
+ * Defines the default socket timeout (<tt>SO_TIMEOUT</tt>) in milliseconds which is the
+ * timeout for waiting for data. A timeout value of zero is interpreted as an infinite
+ * timeout. This value is used when no socket timeout is set in the
+ * method parameters.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ * @see java.net.SocketOptions#SO_TIMEOUT
+ */
+ public static final String SO_TIMEOUT = "http.socket.timeout";
+
+ /**
+ * Determines whether Nagle's algorithm is to be used. The Nagle's algorithm
+ * tries to conserve bandwidth by minimizing the number of segments that are
+ * sent. When applications wish to decrease network latency and increase
+ * performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY).
+ * Data will be sent earlier, at the cost of an increase in bandwidth consumption.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ * @see java.net.SocketOptions#TCP_NODELAY
+ */
+ public static final String TCP_NODELAY = "http.tcp.nodelay";
+
+ /**
+ * Determines the size of the internal socket buffer used to buffer data
+ * while receiving / transmitting HTTP messages.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String SOCKET_BUFFER_SIZE = "http.socket.buffer-size";
+
+ /**
+ * Sets SO_LINGER with the specified linger time in seconds. The maximum timeout
+ * value is platform specific. Value <tt>0</tt> implies that the option is disabled.
+ * Value <tt>-1</tt> implies that the JRE default is used. The setting only affects
+ * socket close.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ * @see java.net.SocketOptions#SO_LINGER
+ */
+ public static final String SO_LINGER = "http.socket.linger";
+
+ /**
+ * Determines the timeout until a connection is etablished. A value of zero
+ * means the timeout is not used. The default value is zero.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String CONNECTION_TIMEOUT = "http.connection.timeout";
+
+ /**
+ * Determines whether stale connection check is to be used. Disabling
+ * stale connection check may result in slight performance improvement
+ * at the risk of getting an I/O error when executing a request over a
+ * connection that has been closed at the server side.
+ * <p>
+ * This parameter expects a value of type {@link Boolean}.
+ * </p>
+ */
+ public static final String STALE_CONNECTION_CHECK = "http.connection.stalecheck";
+
+ /**
+ * Determines the maximum line length limit. If set to a positive value, any HTTP
+ * line exceeding this limit will cause an IOException. A negative or zero value
+ * will effectively disable the check.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String MAX_LINE_LENGTH = "http.connection.max-line-length";
+
+ /**
+ * Determines the maximum HTTP header count allowed. If set to a positive value,
+ * the number of HTTP headers received from the data stream exceeding this limit
+ * will cause an IOException. A negative or zero value will effectively disable
+ * the check.
+ * <p>
+ * This parameter expects a value of type {@link Integer}.
+ * </p>
+ */
+ public static final String MAX_HEADER_COUNT = "http.connection.max-header-count";
+
+}
diff --git a/core/java/org/apache/http/params/HttpConnectionParams.java b/core/java/org/apache/http/params/HttpConnectionParams.java
new file mode 100644
index 0000000..a7b31fc
--- /dev/null
+++ b/core/java/org/apache/http/params/HttpConnectionParams.java
@@ -0,0 +1,229 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/params/HttpConnectionParams.java $
+ * $Revision: 576089 $
+ * $Date: 2007-09-16 05:39:56 -0700 (Sun, 16 Sep 2007) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.params;
+
+/**
+ * An adaptor for accessing connection parameters in {@link HttpParams}.
+ * <br/>
+ * Note that the <i>implements</i> relation to {@link CoreConnectionPNames}
+ * is for compatibility with existing application code only. References to
+ * the parameter names should use the interface, not this class.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision: 576089 $
+ *
+ * @since 4.0
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public final class HttpConnectionParams implements CoreConnectionPNames {
+
+ /**
+ */
+ private HttpConnectionParams() {
+ super();
+ }
+
+ /**
+ * Returns the default socket timeout (<tt>SO_TIMEOUT</tt>) in milliseconds which is the
+ * timeout for waiting for data. A timeout value of zero is interpreted as an infinite
+ * timeout. This value is used when no socket timeout is set in the
+ * method parameters.
+ *
+ * @return timeout in milliseconds
+ */
+ public static int getSoTimeout(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getIntParameter(CoreConnectionPNames.SO_TIMEOUT, 0);
+ }
+
+ /**
+ * Sets the default socket timeout (<tt>SO_TIMEOUT</tt>) in milliseconds which is the
+ * timeout for waiting for data. A timeout value of zero is interpreted as an infinite
+ * timeout. This value is used when no socket timeout is set in the
+ * method parameters.
+ *
+ * @param timeout Timeout in milliseconds
+ */
+ public static void setSoTimeout(final HttpParams params, int timeout) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);
+
+ }
+
+ /**
+ * Tests if Nagle's algorithm is to be used.
+ *
+ * @return <tt>true</tt> if the Nagle's algorithm is to NOT be used
+ * (that is enable TCP_NODELAY), <tt>false</tt> otherwise.
+ */
+ public static boolean getTcpNoDelay(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getBooleanParameter
+ (CoreConnectionPNames.TCP_NODELAY, true);
+ }
+
+ /**
+ * Determines whether Nagle's algorithm is to be used. The Nagle's algorithm
+ * tries to conserve bandwidth by minimizing the number of segments that are
+ * sent. When applications wish to decrease network latency and increase
+ * performance, they can disable Nagle's algorithm (that is enable TCP_NODELAY).
+ * Data will be sent earlier, at the cost of an increase in bandwidth consumption.
+ *
+ * @param value <tt>true</tt> if the Nagle's algorithm is to NOT be used
+ * (that is enable TCP_NODELAY), <tt>false</tt> otherwise.
+ */
+ public static void setTcpNoDelay(final HttpParams params, boolean value) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, value);
+ }
+
+ public static int getSocketBufferSize(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getIntParameter
+ (CoreConnectionPNames.SOCKET_BUFFER_SIZE, -1);
+ }
+
+ public static void setSocketBufferSize(final HttpParams params, int size) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, size);
+ }
+
+ /**
+ * Returns linger-on-close timeout. Value <tt>0</tt> implies that the option is
+ * disabled. Value <tt>-1</tt> implies that the JRE default is used.
+ *
+ * @return the linger-on-close timeout
+ */
+ public static int getLinger(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getIntParameter(CoreConnectionPNames.SO_LINGER, -1);
+ }
+
+ /**
+ * Returns linger-on-close timeout. This option disables/enables immediate return
+ * from a close() of a TCP Socket. Enabling this option with a non-zero Integer
+ * timeout means that a close() will block pending the transmission and
+ * acknowledgement of all data written to the peer, at which point the socket is
+ * closed gracefully. Value <tt>0</tt> implies that the option is
+ * disabled. Value <tt>-1</tt> implies that the JRE default is used.
+ *
+ * @param value the linger-on-close timeout
+ */
+ public static void setLinger(final HttpParams params, int value) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setIntParameter(CoreConnectionPNames.SO_LINGER, value);
+ }
+
+ /**
+ * Returns the timeout until a connection is etablished. A value of zero
+ * means the timeout is not used. The default value is zero.
+ *
+ * @return timeout in milliseconds.
+ */
+ public static int getConnectionTimeout(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getIntParameter
+ (CoreConnectionPNames.CONNECTION_TIMEOUT, 0);
+ }
+
+ /**
+ * Sets the timeout until a connection is etablished. A value of zero
+ * means the timeout is not used. The default value is zero.
+ *
+ * @param timeout Timeout in milliseconds.
+ */
+ public static void setConnectionTimeout(final HttpParams params, int timeout) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setIntParameter
+ (CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
+ }
+
+ /**
+ * Tests whether stale connection check is to be used. Disabling
+ * stale connection check may result in slight performance improvement
+ * at the risk of getting an I/O error when executing a request over a
+ * connection that has been closed at the server side.
+ *
+ * @return <tt>true</tt> if stale connection check is to be used,
+ * <tt>false</tt> otherwise.
+ */
+ public static boolean isStaleCheckingEnabled(final HttpParams params) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ return params.getBooleanParameter
+ (CoreConnectionPNames.STALE_CONNECTION_CHECK, true);
+ }
+
+ /**
+ * Defines whether stale connection check is to be used. Disabling
+ * stale connection check may result in slight performance improvement
+ * at the risk of getting an I/O error when executing a request over a
+ * connection that has been closed at the server side.
+ *
+ * @param value <tt>true</tt> if stale connection check is to be used,
+ * <tt>false</tt> otherwise.
+ */
+ public static void setStaleCheckingEnabled(final HttpParams params, boolean value) {
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ params.setBooleanParameter
+ (CoreConnectionPNames.STALE_CONNECTION_CHECK, value);
+ }
+
+}
diff --git a/core/java/org/apache/http/params/HttpParams.java b/core/java/org/apache/http/params/HttpParams.java
new file mode 100644
index 0000000..9562e54
--- /dev/null
+++ b/core/java/org/apache/http/params/HttpParams.java
@@ -0,0 +1,192 @@
+/*
+ * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/params/HttpParams.java $
+ * $Revision: 610763 $
+ * $Date: 2008-01-10 04:01:13 -0800 (Thu, 10 Jan 2008) $
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.params;
+
+/**
+ * Represents a collection of HTTP protocol and framework parameters.
+ *
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision: 610763 $
+ *
+ * @since 4.0
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection} instead.
+ * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ * for further details.
+ */
+@Deprecated
+public interface HttpParams {
+
+ /**
+ * Obtains the value of the given parameter.
+ *
+ * @param name the parent name.
+ *
+ * @return an object that represents the value of the parameter,
+ * <code>null</code> if the parameter is not set or if it
+ * is explicitly set to <code>null</code>
+ *
+ * @see #setParameter(String, Object)
+ */
+ Object getParameter(String name);
+
+ /**
+ * Assigns the value to the parameter with the given name.
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setParameter(String name, Object value);
+
+ /**
+ * Creates a copy of these parameters.
+ *
+ * @return a new set of parameters holding the same values as this one
+ */
+ HttpParams copy();
+
+ /**
+ * Removes the parameter with the specified name.
+ *
+ * @param name parameter name
+ *
+ * @return true if the parameter existed and has been removed, false else.
+ */
+ boolean removeParameter(String name);
+
+ /**
+ * Returns a {@link Long} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Long} that represents the value of the parameter.
+ *
+ * @see #setLongParameter(String, long)
+ */
+ long getLongParameter(String name, long defaultValue);
+
+ /**
+ * Assigns a {@link Long} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setLongParameter(String name, long value);
+
+ /**
+ * Returns an {@link Integer} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Integer} that represents the value of the parameter.
+ *
+ * @see #setIntParameter(String, int)
+ */
+ int getIntParameter(String name, int defaultValue);
+
+ /**
+ * Assigns an {@link Integer} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setIntParameter(String name, int value);
+
+ /**
+ * Returns a {@link Double} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Double} that represents the value of the parameter.
+ *
+ * @see #setDoubleParameter(String, double)
+ */
+ double getDoubleParameter(String name, double defaultValue);
+
+ /**
+ * Assigns a {@link Double} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setDoubleParameter(String name, double value);
+
+ /**
+ * Returns a {@link Boolean} parameter value with the given name.
+ * If the parameter is not explicitly set, the default value is returned.
+ *
+ * @param name the parent name.
+ * @param defaultValue the default value.
+ *
+ * @return a {@link Boolean} that represents the value of the parameter.
+ *
+ * @see #setBooleanParameter(String, boolean)
+ */
+ boolean getBooleanParameter(String name, boolean defaultValue);
+
+ /**
+ * Assigns a {@link Boolean} to the parameter with the given name
+ *
+ * @param name parameter name
+ * @param value parameter value
+ */
+ HttpParams setBooleanParameter(String name, boolean value);
+
+ /**
+ * Checks if a boolean parameter is set to <code>true</code>.
+ *
+ * @param name parameter name
+ *
+ * @return <tt>true</tt> if the parameter is set to value <tt>true</tt>,
+ * <tt>false</tt> if it is not set or set to <code>false</code>
+ */
+ boolean isParameterTrue(String name);
+
+ /**
+ * Checks if a boolean parameter is not set or <code>false</code>.
+ *
+ * @param name parameter name
+ *
+ * @return <tt>true</tt> if the parameter is either not set or
+ * set to value <tt>false</tt>,
+ * <tt>false</tt> if it is set to <code>true</code>
+ */
+ boolean isParameterFalse(String name);
+
+}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index d1b1a1a..0b737a7 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "SensorManager"
+#include <map>
+
#include <utils/Log.h>
#include <utils/Looper.h>
@@ -44,7 +46,6 @@
jfieldID vendor;
jfieldID version;
jfieldID handle;
- jfieldID type;
jfieldID range;
jfieldID resolution;
jfieldID power;
@@ -55,6 +56,7 @@
jfieldID requiredPermission;
jfieldID maxDelay;
jfieldID flags;
+ jmethodID setType;
} gSensorOffsets;
@@ -71,7 +73,6 @@
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
- sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I");
sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
@@ -84,6 +85,47 @@
"Ljava/lang/String;");
sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
+ sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
+}
+
+/**
+ * A key comparator predicate.
+ * It is used to intern strings associated with Sensor data.
+ * It defines a 'Strict weak ordering' for the interned strings.
+ */
+class InternedStringCompare {
+public:
+ bool operator()(const String8* string1, const String8* string2) const {
+ if (string1 == NULL) {
+ return string2 != NULL;
+ }
+ return string1->compare(*string2) < 0;
+ }
+};
+
+/**
+ * A localized interning mechanism for Sensor strings.
+ * We implement our own interning to avoid the overhead of using java.lang.String#intern().
+ * It is common that Vendor, StringType, and RequirePermission data is common between many of the
+ * Sensors, by interning the memory usage to represent Sensors is optimized.
+ */
+static jstring
+getInternedString(JNIEnv *env, const String8* string) {
+ static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
+
+ jstring internedString;
+ std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
+ if (iterator != internedStrings.end()) {
+ internedString = iterator->second;
+ } else {
+ jstring localString = env->NewStringUTF(string->string());
+ // we are implementing our own interning so expect these strings to be backed by global refs
+ internedString = (jstring) env->NewGlobalRef(localString);
+ internedStrings.insert(std::make_pair(string, internedString));
+ env->DeleteLocalRef(localString);
+ }
+
+ return internedString;
}
static jint
@@ -93,20 +135,19 @@
Sensor const* const* sensorList;
size_t count = mgr.getSensorList(&sensorList);
- if (size_t(next) >= count)
+ if (size_t(next) >= count) {
return -1;
+ }
Sensor const* const list = sensorList[next];
const SensorOffsets& sensorOffsets(gSensorOffsets);
- jstring name = env->NewStringUTF(list->getName().string());
- jstring vendor = env->NewStringUTF(list->getVendor().string());
- jstring stringType = env->NewStringUTF(list->getStringType().string());
- jstring requiredPermission = env->NewStringUTF(list->getRequiredPermission().string());
+ jstring name = getInternedString(env, &list->getName());
+ jstring vendor = getInternedString(env, &list->getVendor());
+ jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
env->SetObjectField(sensor, sensorOffsets.name, name);
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
env->SetIntField(sensor, sensorOffsets.version, list->getVersion());
env->SetIntField(sensor, sensorOffsets.handle, list->getHandle());
- env->SetIntField(sensor, sensorOffsets.type, list->getType());
env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue());
env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage());
@@ -115,11 +156,14 @@
list->getFifoReservedEventCount());
env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
list->getFifoMaxEventCount());
- env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
env->SetObjectField(sensor, sensorOffsets.requiredPermission,
requiredPermission);
env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
+ if (env->CallBooleanMethod(sensor, sensorOffsets.setType, list->getType()) == JNI_FALSE) {
+ jstring stringType = getInternedString(env, &list->getStringType());
+ env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
+ }
next++;
return size_t(next) < count ? next : 0;
}
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index aabf320..7497d8b 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -598,15 +598,10 @@
ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
return BAD_VALUE;
}
- status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
- if (err != NO_ERROR) {
- ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
- return err;
- }
- // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
- // change.
- err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
+ // Set user dimensions only
+ // The producer dimensions are owned by GL
+ status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
if (err != NO_ERROR) {
ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
err);
@@ -750,4 +745,3 @@
gCameraDeviceMethods,
NELEM(gCameraDeviceMethods));
}
-
diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp
index c8aa22f7..24f8f67 100644
--- a/core/jni/android_server_FingerprintManager.cpp
+++ b/core/jni/android_server_FingerprintManager.cpp
@@ -28,7 +28,7 @@
namespace android {
-static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(1, 0);
+static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0);
static const char* FINGERPRINT_SERVICE = "com/android/server/fingerprint/FingerprintService";
static struct {
@@ -55,15 +55,15 @@
arg1 = msg.data.acquired.acquired_info;
break;
case FINGERPRINT_PROCESSED:
- arg1 = msg.data.processed.id;
+ arg1 = msg.data.processed.finger.fid;
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
- arg1 = msg.data.enroll.id;
+ arg1 = msg.data.enroll.finger.fid;
arg2 = msg.data.enroll.samples_remaining;
- arg3 = msg.data.enroll.data_collected_bmp;
+ arg3 = 0;
break;
case FINGERPRINT_TEMPLATE_REMOVED:
- arg1 = msg.data.removed.id;
+ arg1 = msg.data.removed.finger.fid;
break;
default:
ALOGE("fingerprint: invalid msg: %d", msg.type);
@@ -99,7 +99,7 @@
static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
ALOG(LOG_VERBOSE, LOG_TAG, "nativeEnroll()\n");
- int ret = gContext.device->enroll(gContext.device, timeout);
+ int ret = gContext.device->enroll(gContext.device, 0, timeout);
return reinterpret_cast<jint>(ret);
}
@@ -111,7 +111,10 @@
static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
ALOG(LOG_VERBOSE, LOG_TAG, "nativeRemove(%d)\n", fingerprintId);
- int ret = gContext.device->remove(gContext.device, fingerprintId);
+ fingerprint_finger_id_t finger;
+ finger.gid = 0;
+ finger.fid = fingerprintId;
+ int ret = gContext.device->remove(gContext.device, finger);
return reinterpret_cast<jint>(ret);
}
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 2df13b7..6c95b8a 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -159,7 +159,7 @@
}
struct logger_list *logger_list = android_logger_list_open(
- LOG_ID_EVENTS, O_RDONLY | O_NONBLOCK, 0, 0);
+ LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0);
if (!logger_list) {
jniThrowIOException(env, errno);
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index f539127..9e49afb 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -82,7 +82,7 @@
static jint android_view_HardwareLayer_getTexName(JNIEnv* env, jobject clazz,
jlong layerUpdaterPtr) {
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
- return layer->backingLayer()->getTexture();
+ return layer->backingLayer()->getTextureId();
}
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 7f6c50f..bfa0534 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -49,6 +49,7 @@
#include <AnimationContext.h>
#include <DisplayListRenderer.h>
+#include <FrameInfo.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
@@ -394,7 +395,7 @@
proxy->initialize(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s. (and width & height are unused, TODO remove them)
- proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
+ proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0, 1.0f);
return (jlong) proxy;
}
@@ -406,8 +407,11 @@
static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
+ nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ UiFrameInfoBuilder(proxy->frameInfo())
+ .setVsync(vsync, vsync)
+ .addFlag(FrameInfoFlags::kSurfaceCanvas);
+ proxy->syncAndDrawFrame();
}
static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 068b24e..ad93301 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -281,10 +281,10 @@
static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
jint width, jint height,
jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
- jint ambientShadowAlpha, jint spotShadowAlpha) {
+ jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
- ambientShadowAlpha, spotShadowAlpha);
+ ambientShadowAlpha, spotShadowAlpha, density);
}
static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -294,9 +294,13 @@
}
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
+ jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
+ LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
+ "Mismatched size expectations, given %d expected %d",
+ frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
+ env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
+ return proxy->syncAndDrawFrame();
}
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
@@ -391,10 +395,10 @@
}
static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject javaFileDescriptor) {
+ jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
- proxy->dumpProfileInfo(fd);
+ proxy->dumpProfileInfo(fd, dumpFlags);
}
// ----------------------------------------------------------------------------
@@ -425,9 +429,9 @@
{ "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
{ "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
- { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
+ { "nSetup", "(JIIFFFFIIF)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
- { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+ { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
@@ -442,7 +446,7 @@
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
{ "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
- { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
+ { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
(void*) android_view_ThreadedRenderer_setupShadersDiskCache },
};
diff --git a/core/res/res/color/control_highlight_material.xml b/core/res/res/color/control_highlight_material.xml
index c3587db..2492a4d 100644
--- a/core/res/res/color/control_highlight_material.xml
+++ b/core/res/res/color/control_highlight_material.xml
@@ -17,7 +17,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
android:state_enabled="true"
- android:alpha="?attr/disabledAlpha"
+ android:alpha="@dimen/highlight_alpha_material_colored"
android:color="?attr/colorControlActivated" />
<item android:color="?attr/colorControlHighlight" />
</selector>
diff --git a/core/res/res/color/highlighted_text_material.xml b/core/res/res/color/highlighted_text_material.xml
new file mode 100644
index 0000000..fee277a
--- /dev/null
+++ b/core/res/res/color/highlighted_text_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.4"
+ android:color="?attr/colorAccent" />
+</selector>
diff --git a/core/res/res/color/list_highlight_material.xml b/core/res/res/color/list_highlight_material.xml
new file mode 100644
index 0000000..116ab29
--- /dev/null
+++ b/core/res/res/color/list_highlight_material.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_activated="true"
+ android:alpha="@dimen/highlight_alpha_material_colored"
+ android:color="?attr/colorControlActivated" />
+ <item android:color="?attr/colorControlHighlight" />
+</selector>
diff --git a/core/res/res/color/tab_highlight_material.xml b/core/res/res/color/tab_highlight_material.xml
new file mode 100644
index 0000000..7b2922bd
--- /dev/null
+++ b/core/res/res/color/tab_highlight_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="@dimen/highlight_alpha_material_colored"
+ android:color="?attr/colorControlActivated" />
+</selector>
diff --git a/core/res/res/color/tab_indicator_text_material.xml b/core/res/res/color/tab_indicator_text_material.xml
new file mode 100644
index 0000000..019fa67
--- /dev/null
+++ b/core/res/res/color/tab_indicator_text_material.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true"
+ android:color="?attr/textColorPrimary" />
+ <item android:color="?attr/textColorSecondary" />
+</selector>
diff --git a/core/res/res/color/white_disabled_material.xml b/core/res/res/color/white_disabled_material.xml
new file mode 100644
index 0000000..c61f900
--- /dev/null
+++ b/core/res/res/color/white_disabled_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@color/white"
+ android:alpha="?attr/disabledAlpha" />
+</selector>
diff --git a/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png
deleted file mode 100644
index fbb2e0c..0000000
--- a/core/res/res/drawable-hdpi/progress_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png
deleted file mode 100644
index 92d4b05..0000000
--- a/core/res/res/drawable-mdpi/progress_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png
deleted file mode 100644
index e3c4eeb..0000000
--- a/core/res/res/drawable-xhdpi/progress_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png b/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png
deleted file mode 100644
index 452f45c..0000000
--- a/core/res/res/drawable-xxhdpi/progress_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/action_bar_item_background_material.xml b/core/res/res/drawable/action_bar_item_background_material.xml
new file mode 100644
index 0000000..8228e3f
--- /dev/null
+++ b/core/res/res/drawable/action_bar_item_background_material.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlHighlight"
+ android:radius="20dp" />
diff --git a/core/res/res/drawable/control_background_material.xml b/core/res/res/drawable/control_background_material.xml
index ae3181a..7b78349 100644
--- a/core/res/res/drawable/control_background_material.xml
+++ b/core/res/res/drawable/control_background_material.xml
@@ -15,4 +15,5 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/control_highlight_material" />
+ android:color="@color/control_highlight_material"
+ android:radius="20dp" />
diff --git a/core/res/res/drawable/list_highlight_material.xml b/core/res/res/drawable/list_highlight_material.xml
new file mode 100644
index 0000000..5a930c4
--- /dev/null
+++ b/core/res/res/drawable/list_highlight_material.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/list_highlight_material">
+ <item android:id="@id/mask">
+ <color android:color="@color/white" />
+ </item>
+</ripple>
diff --git a/core/res/res/drawable/progress_horizontal_material.xml b/core/res/res/drawable/progress_horizontal_material.xml
index 6b64337..c1795640 100644
--- a/core/res/res/drawable/progress_horizontal_material.xml
+++ b/core/res/res/drawable/progress_horizontal_material.xml
@@ -15,22 +15,32 @@
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@id/background">
- <nine-patch android:src="@drawable/progress_mtrl_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
+ <item android:id="@id/background"
+ android:gravity="center_vertical|fill_horizontal">
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlNormal">
+ <size android:height="@dimen/progress_bar_height_material" />
+ <solid android:color="@color/white_disabled_material" />
+ </shape>
</item>
- <item android:id="@id/secondaryProgress">
+ <item android:id="@id/secondaryProgress"
+ android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
- <nine-patch android:src="@drawable/progress_mtrl_alpha"
- android:tint="?attr/colorControlActivated"
- android:alpha="?attr/disabledAlpha" />
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlActivated">
+ <size android:height="@dimen/progress_bar_height_material" />
+ <solid android:color="@color/white_disabled_material" />
+ </shape>
</scale>
</item>
- <item android:id="@id/progress">
+ <item android:id="@id/progress"
+ android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
- <nine-patch android:src="@drawable/progress_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlActivated">
+ <size android:height="@dimen/progress_bar_height_material" />
+ <solid android:color="@color/white" />
+ </shape>
</scale>
</item>
</layer-list>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_material.xml b/core/res/res/drawable/scrubber_progress_horizontal_material.xml
index 89a1787..86a85c3 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_material.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_material.xml
@@ -15,32 +15,42 @@
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@id/background">
- <nine-patch android:src="@drawable/scrubber_track_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+ <item android:id="@id/background"
+ android:gravity="center_vertical|fill_horizontal">
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlNormal">
+ <size android:height="@dimen/scrubber_track_height_material" />
+ <solid android:color="@color/white_disabled_material" />
+ </shape>
</item>
- <item android:id="@id/secondaryProgress">
+ <item android:id="@id/secondaryProgress"
+ android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
<selector>
- <item android:state_enabled="false">
- <color android:color="@color/transparent" />
- </item>
+ <item android:state_enabled="false"
+ android:drawable="@color/transparent" />
<item>
- <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlActivated">
+ <size android:height="@dimen/scrubber_track_height_material" />
+ <solid android:color="@color/white_disabled_material" />
+ </shape>
</item>
</selector>
</scale>
</item>
- <item android:id="@id/progress">
+ <item android:id="@id/progress"
+ android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
<selector>
- <item android:state_enabled="false">
- <color android:color="@color/transparent" />
- </item>
+ <item android:state_enabled="false"
+ android:drawable="@color/transparent" />
<item>
- <nine-patch android:src="@drawable/scrubber_primary_mtrl_alpha"
- android:tint="?attr/colorControlActivated" />
+ <shape android:shape="rectangle"
+ android:tint="?attr/colorControlActivated">
+ <size android:height="@dimen/progress_bar_height_material" />
+ <solid android:color="@color/white" />
+ </shape>
</item>
</selector>
</scale>
diff --git a/core/res/res/drawable/switch_track_material.xml b/core/res/res/drawable/switch_track_material.xml
index a825fe4..8b028d3 100644
--- a/core/res/res/drawable/switch_track_material.xml
+++ b/core/res/res/drawable/switch_track_material.xml
@@ -16,12 +16,12 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="center_vertical|fill_horizontal"
- android:start="2dp"
- android:end="2dp">
+ android:start="4dp"
+ android:end="4dp">
<shape android:shape="rectangle"
android:tint="@color/switch_track_material">
<corners android:radius="7dp" />
- <solid android:color="#4dffffff" />
+ <solid android:color="@color/white_disabled_material" />
<size android:height="14dp" />
</shape>
</item>
diff --git a/core/res/res/drawable/tab_indicator_material.xml b/core/res/res/drawable/tab_indicator_material.xml
index fc52305..958f57f 100644
--- a/core/res/res/drawable/tab_indicator_material.xml
+++ b/core/res/res/drawable/tab_indicator_material.xml
@@ -14,7 +14,15 @@
limitations under the License.
-->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingMode="nest">
+ <item>
+ <ripple android:color="@color/tab_highlight_material">
+ <item android:id="@id/mask">
+ <color android:color="@color/white" />
+ </item>
+ </ripple>
+ </item>
<item android:gravity="bottom">
<shape android:shape="rectangle"
android:tint="?attr/colorControlActivated">
diff --git a/core/res/res/layout/alert_dialog_button_bar_material.xml b/core/res/res/layout/alert_dialog_button_bar_material.xml
new file mode 100644
index 0000000..891bcd5
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_button_bar_material.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<com.android.internal.widget.ButtonBarLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/buttonPanel"
+ style="?attr/buttonBarStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="locale"
+ android:orientation="horizontal"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:gravity="bottom">
+
+ <Button
+ android:id="@+id/button3"
+ style="?attr/buttonBarNeutralButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Space
+ android:id="@+id/spacer"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+
+ <Button
+ android:id="@+id/button2"
+ style="?attr/buttonBarNegativeButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@+id/button1"
+ style="?attr/buttonBarPositiveButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+</com.android.internal.widget.ButtonBarLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 29bfaa7..c8735b1 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -101,33 +101,5 @@
android:layout_height="wrap_content" />
</FrameLayout>
- <LinearLayout android:id="@+id/buttonPanel"
- style="?attr/buttonBarStyle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layoutDirection="locale"
- android:orientation="horizontal"
- android:paddingStart="12dp"
- android:paddingEnd="12dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:gravity="bottom">
- <Button android:id="@+id/button3"
- style="?attr/buttonBarNeutralButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:visibility="invisible" />
- <Button android:id="@+id/button2"
- style="?attr/buttonBarNegativeButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <Button android:id="@+id/button1"
- style="?attr/buttonBarPositiveButtonStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
+ <include layout="@layout/alert_dialog_button_bar_material" />
</LinearLayout>
diff --git a/core/res/res/layout/time_header_label.xml b/core/res/res/layout/time_header_label.xml
index 6ccde33..46e7c54 100644
--- a/core/res/res/layout/time_header_label.xml
+++ b/core/res/res/layout/time_header_label.xml
@@ -14,69 +14,71 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/time_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="@dimen/timepicker_separator_padding"
- android:gravity="center">
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:padding="@dimen/timepicker_separator_padding">
- <LinearLayout
+ <!-- The hour should always be to the left of the separator,
+ regardless of the current locale's layout direction. -->
+ <TextView
+ android:id="@+id/hours"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="bottom"
- android:orientation="horizontal"
- android:layoutDirection="ltr">
+ android:layout_toLeftOf="@+id/separator"
+ android:layout_alignBaseline="@+id/separator"
+ android:gravity="right" />
- <TextView
- android:id="@+id/hours"
+ <TextView
+ android:id="@+id/separator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/timepicker_separator_padding"
+ android:layout_marginRight="@dimen/timepicker_separator_padding"
+ android:layout_centerInParent="true"
+ android:importantForAccessibility="no" />
+
+ <!-- The minutes should always be to the left of the separator,
+ regardless of the current locale's layout direction. -->
+ <TextView
+ android:id="@+id/minutes"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/separator"
+ android:layout_alignBaseline="@+id/separator"
+ android:gravity="left" />
+
+ <!-- The layout alignment of this view will switch between toRightOf
+ @id/minutes and toLeftOf @id/hours depending on the locale. -->
+ <LinearLayout
+ android:id="@+id/ampm_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/minutes"
+ android:layout_alignBaseline="@+id/minutes"
+ android:orientation="vertical"
+ android:baselineAlignedChildIndex="1">
+ <CheckedTextView
+ android:id="@+id/am_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="right"
- android:layoutDirection="locale" />
-
- <TextView
- android:id="@+id/separator"
+ android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
+ android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
+ android:paddingTop="@dimen/timepicker_ampm_vertical_padding"
+ android:lines="1"
+ android:ellipsize="none" />
+ <CheckedTextView
+ android:id="@+id/pm_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/timepicker_separator_padding"
- android:layout_marginRight="@dimen/timepicker_separator_padding"
- android:importantForAccessibility="no"
- android:layoutDirection="locale" />
-
- <TextView
- android:id="@+id/minutes"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="left"
- android:layoutDirection="locale" />
-
- <LinearLayout
- android:id="@+id/ampm_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:baselineAlignedChildIndex="1"
- android:layoutDirection="locale">
- <CheckedTextView
- android:id="@+id/am_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
- android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
- android:paddingTop="@dimen/timepicker_ampm_vertical_padding"
- android:lines="1"
- android:ellipsize="none" />
- <CheckedTextView
- android:id="@+id/pm_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
- android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
- android:paddingTop="@dimen/timepicker_pm_top_padding"
- android:lines="1"
- android:ellipsize="none" />
- </LinearLayout>
+ android:paddingStart="@dimen/timepicker_ampm_horizontal_padding"
+ android:paddingEnd="@dimen/timepicker_ampm_horizontal_padding"
+ android:paddingTop="@dimen/timepicker_pm_top_padding"
+ android:lines="1"
+ android:ellipsize="none" />
</LinearLayout>
-</FrameLayout>
+</RelativeLayout>
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 7a9f90a..cb25dbe 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -28,7 +28,7 @@
android:layout_gravity="center" />
<android.widget.RadialTimePickerView
android:id="@+id/radial_picker"
- android:layout_width="@dimen/timepicker_radial_picker_dimen"
+ android:layout_width="wrap_content"
android:layout_height="@dimen/timepicker_radial_picker_dimen"
android:layout_gravity="center"
android:layout_marginTop="?attr/dialogPreferredPadding"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 7c4c2d0..a33f8af 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Jou SIM-kaart is PUK-gesluit. Voer die PUK-kode in om dit te ontsluit."</string>
<string name="needPuk2" msgid="4526033371987193070">"Sleutel PUK2 in om SIM-kaart oop te sluit."</string>
<string name="enablePin" msgid="209412020907207950">"Onsuksesvol, aktiveer SIM-/RUIM-slot."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende poging voordat SIM gesluit word."</item>
- <item quantity="other" msgid="7530597808358774740">"Jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende pogings voordat SIM gesluit word."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Jy het <xliff:g id="NUMBER_1">%d</xliff:g> pogings oor voordat SIM gesluit word.</item>
+ <item quantity="one">Jy het <xliff:g id="NUMBER_0">%d</xliff:g> poging oor voordat SIM gesluit word.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Inkomender beller-ID"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil Verken-met-raak aktiveer. Wanneer Verken-met-raak aangeskakel is, kan jy beskrywings van wat onder jou vinger is hoor of sien, of jy kan gebare uitvoer om interaksie met die foon te hê ."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 maand gelede"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Voor 1 maand gelede"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 sekonde gelede"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sekondes gelede"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuut gelede"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minute gelede"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 uur gelede"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> uur gelede"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Afgelope <xliff:g id="COUNT_1">%d</xliff:g> dae</item>
+ <item quantity="one">Afgelope <xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Verlede maand"</string>
<string name="older" msgid="5211975022815554840">"Ouer"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"gister"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> dae gelede"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"oor 1 sekonde"</item>
- <item quantity="other" msgid="1241926116443974687">"oor <xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"oor 1 minuut"</item>
- <item quantity="other" msgid="3330713936399448749">"oor <xliff:g id="COUNT">%d</xliff:g> minute"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"oor 1 uur"</item>
- <item quantity="other" msgid="547290677353727389">"oor <xliff:g id="COUNT">%d</xliff:g> uur"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"môre"</item>
- <item quantity="other" msgid="5109449375100953247">"oor <xliff:g id="COUNT">%d</xliff:g> dae"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 sek. gelede"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> sek. gelede"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min. gelede"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> min. gelede"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 uur gelede"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> uur gelede"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"gister"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> dae gelede"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"oor 1 sek."</item>
- <item quantity="other" msgid="5495880108825805108">"oor <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"oor 1 min."</item>
- <item quantity="other" msgid="4216113292706568726">"oor <xliff:g id="COUNT">%d</xliff:g> minute"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"oor 1 uur"</item>
- <item quantity="other" msgid="3705373766798013406">"oor <xliff:g id="COUNT">%d</xliff:g> uur"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"môre"</item>
- <item quantity="other" msgid="2973062968038355991">"oor <xliff:g id="COUNT">%d</xliff:g> dae"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"op <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"by <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"in <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"weke"</string>
<string name="year" msgid="4001118221013892076">"jaar"</string>
<string name="years" msgid="6881577717993213522">"jaar"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekonde"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minute"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ure"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekondes</item>
+ <item quantity="one">1 sekonde</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="one">1 minuut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> uur</item>
+ <item quantity="one">1 uur</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hierdie video is nie geldig vir stroming na hierdie toestel nie."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan nie hierdie video speel nie."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Luitone"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende luitoon"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi-netwerk beskikbaar"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi-netwerke beskikbaar"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Oop Wi-Fi-netwerke beskikbaar"</item>
- <item quantity="other" msgid="7915895323644292768">"Oop Wi-Fi-netwerke beskikbaar"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi netwerke beskikbaar</item>
+ <item quantity="one">Wi-Fi-netwerk beskikbaar</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Oop Wi-Fi-netwerke beskikbaar</item>
+ <item quantity="one">Oop Wi-Fi-netwerk beskikbaar</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Meld aan by Wi-Fi-netwerk"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Meld aan by netwerk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Gekoppel as \'n mediatoestel"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Gekoppel as \'n kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Gekoppel as \'n MIDI-toestel"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Gekoppel as \'n installeerder"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Gekoppel aan \'n USB-toebehoorsel"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Raak vir ander USB-opsies."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Slaan oor"</string>
<string name="no_matches" msgid="8129421908915840737">"Geen passings nie"</string>
<string name="find_on_page" msgid="1946799233822820384">"Vind op bladsy"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 passing"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 passing</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Klaar"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Ontheg tans USB-geheue..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Ontheg tans SD-kaart..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Skep \'n PIN vir wysigingbeperkings"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN\'e kom nie ooreen nie. Probeer weer."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN is te kort. Moet ten minste 4 syfers wees."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Probeer weer oor 1 sekonde"</item>
- <item quantity="other" msgid="4730868920742952817">"Probeer weer oor <xliff:g id="COUNT">%d</xliff:g> sekondes"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Probeer weer oor <xliff:g id="COUNT">%d</xliff:g> sekondes</item>
+ <item quantity="one">Probeer weer oor 1 sekonde</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Probeer later weer"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Swiep van bo af na onder om volskerm te verlaat."</string>
<string name="done_label" msgid="2093726099505892398">"Klaar"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Om batterylewe te help verbeter, verminder batterybespaarder jou toestel se werkverrigting en beperk vibrasie, liggingdienste en die meeste agtergronddata. E-pos, boodskappe en ander programme wat op sinkronisering staatmaak, sal dalk nie opdateer tensy jy hulle oopmaak nie.\n\nBatterybespaarder skakel outomaties af wanneer jou toestel besig is om te laai."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat jou ontspantyd om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> eindig"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Tot jou aftyd verby is"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Vir een minuut (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Vir %1$d minute (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Vir een uur (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Vir %1$d ure (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Een minuut lank"</item>
- <item quantity="other" msgid="6924190729213550991">"%d minute lank"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Een uur lank"</item>
- <item quantity="other" msgid="5408537517529822157">"%d uur lank"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d minute lank (tot <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Een minuut lank (tot <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d uur lank (tot <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Een uur lank (tot <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d minute lank</item>
+ <item quantity="one">Een minuut lank</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d uur lank</item>
+ <item quantity="one">Een uur lank</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Onbepaalde tyd"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Vou in"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a946741..a8dea11 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM ካርድዎ PUK-የተቆለፈ ነው።የPUK ኮዱን በመተየብ ይክፈቱት።"</string>
<string name="needPuk2" msgid="4526033371987193070">" SIM ለመክፈት PUK2 ተይብ።"</string>
<string name="enablePin" msgid="209412020907207950">"አልተሳካም፣ የሲም/RUIM ቁልፍን አንቃ።"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"ሲምዎ ከመቆለፉ በፊት <xliff:g id="NUMBER">%d</xliff:g> ሙከራ ይቀርዎታል።"</item>
- <item quantity="other" msgid="7530597808358774740">"ሲምዎ ከመቆለፉ በፊት <xliff:g id="NUMBER">%d</xliff:g> ሙከራዎች ይቀሩዎታል።"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"የገቢ ደዋይID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"ከ1 ሴኮንድ በፊት"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> ሰኮንዶች በፊት"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"ከ 1 ደቂቃ በፊት"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች በፊት"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"ከ1 ሰዓት በፊት"</item>
- <item quantity="other" msgid="2467273239587587569">"ከ <xliff:g id="COUNT">%d</xliff:g> ሰዓት በፊት"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">የመጨረሻዎቹ <xliff:g id="COUNT_1">%d</xliff:g> ቀኖች</item>
+ <item quantity="other">የመጨረሻዎቹ <xliff:g id="COUNT_1">%d</xliff:g> ቀኖች</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">" ያለፈው ወር"</string>
<string name="older" msgid="5211975022815554840">"የድሮ"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ትላንትና"</item>
- <item quantity="other" msgid="2479586466153314633">"ከ <xliff:g id="COUNT">%d</xliff:g>ቀን በፊት"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"በ1 ሴኮንድ"</item>
- <item quantity="other" msgid="1241926116443974687">"በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"በ1 ደቂቃ ውስጥ"</item>
- <item quantity="other" msgid="3330713936399448749">"በ<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች ውስጥ"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"በ 1 ሰዓት"</item>
- <item quantity="other" msgid="547290677353727389">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ነገ"</item>
- <item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 ሴኮንድ በፊት"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች በፊት"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"ከ 1 ደቂቃ በፊት"</item>
- <item quantity="other" msgid="851164968597150710">"ከ <xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች በፊት"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"ከ1 ሰዓት በፊት"</item>
- <item quantity="other" msgid="6889970745748538901">"ከ <xliff:g id="COUNT">%d</xliff:g> ሰዓት በፊት"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ትላንትና"</item>
- <item quantity="other" msgid="3453342639616481191">"ከ <xliff:g id="COUNT">%d</xliff:g>ቀን በፊት"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"በ1 ሴኮንድ"</item>
- <item quantity="other" msgid="5495880108825805108">"በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"በ1 ደቂቃ ውስጥ"</item>
- <item quantity="other" msgid="4216113292706568726">"በ<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች ውስጥ"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"በ 1 ሰዓት"</item>
- <item quantity="other" msgid="3705373766798013406">"በ <xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ነገ"</item>
- <item quantity="other" msgid="2973062968038355991">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"በ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"በ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ውስጥ <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"ሳምንቶች"</string>
<string name="year" msgid="4001118221013892076">"ዓመት"</string>
<string name="years" msgid="6881577717993213522">"ዓመታት"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 ሴኮንድ"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 ደቂቃ"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ሰዓት"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ሰዓቶች"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ሰከንዶች</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ሰከንዶች</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ደቂቃዎች</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ሰዓቶች</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ምንም"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ጥሪ ድምፆች"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"ያልታወቀ የስልክ ጥሪ ድምፅ"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"የWi-Fi አውታረ መረብ አለ"</item>
- <item quantity="other" msgid="4192424489168397386">"የWi-Fi አውታረ መረቦች አሉ"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"አውታረ መረብ ሲኖር Wi-Fi ክፈት"</item>
- <item quantity="other" msgid="7915895323644292768">"አውታረ መረቦች ሲኖሩ Wi-Fi ክፈት"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">የWi-Fi አውታረ መረቦች አሉ</item>
+ <item quantity="other">የWi-Fi አውታረ መረቦች አሉ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት</item>
+ <item quantity="other">የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ወደ አውታረ መረብ ይግቡ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"እሺ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"እንደ ማህደረ መረጃ መሣሪያ ተያይዟል"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"እንደካሜራ ተያይዟል"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"እንደ MIDI መሣሪያ ተገናኝቷል"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"እንደ ጫኝ ተያይዟል"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ለUSB ተቀጥላ ተያይዟል"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"ለሌላ የUSB አማራጮች ንካ።"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 ጨዋታ"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ከ <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> ከ<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> ከ<xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"ተከናውኗል"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"የUSB ማከማቻ በመንቀል ላይ...."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"የSD ካርድ በመንቀል ላይ...."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"ገደቦችን ለመቀየር ፒን ይፍጠሩ"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"ፒኖች አይዛመዱም። እንደገና ይሞክሩ።"</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"ፒን በጣም አጭር ነው። ቢያንስ 4 አኃዝ መሆን አለበት።"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"በ1 ሰከንድ ውስጥ እንደገና ይሞክሩ"</item>
- <item quantity="other" msgid="4730868920742952817">"በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ</item>
+ <item quantity="other">በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ቆይተው እንደገና ይሞክሩ"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"ከሙሉ ገጽ ማያ ለመውጣት ጣትዎን ከላይ ወደታች ያንሸራትቱ።"</string>
<string name="done_label" msgid="2093726099505892398">"ተከናውኗል"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"የባትሪ ዕድሜን ለማሻሻል ማገዝ እንዲቻል፣ ኢሜይል፣ መልዕክት አላላክ እና ሌሎች በማመሳሰል ላይ የሚመረኮዙ መተግበሪያዎች እርስዎ ካልከፈቱዋቸው በቀር አይዘምኑም።\n\nየባትሪ ኃይል ቆጣቢ የእርስዎ መሣሪያ ኃይል በሚሞላበት ጊዜ በራስ-ሰር ይጠፋል።"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"የጥገና ጊዜዎ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ላይ እስኪያበቃ ድረስ"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"የእርስዎ የማይገኙበት ጊዜ እስከሚያበቃ ድረስ"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ለአንድ ደቂቃ (እስከ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ድረስ)"</item>
- <item quantity="other" msgid="2787867221129368935">"ለ%1$d ደቂቃዎች (እስከ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ድረስ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ለአንድ ሰዓት (እስከ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ድረስ)"</item>
- <item quantity="other" msgid="2827214920627669898">"ለ%1$d ሰዓቶች (እስከ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ድረስ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item>
- <item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ለአንድ ሰዓት"</item>
- <item quantity="other" msgid="5408537517529822157">"ለ%d ሰዓቶች"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">ለ%1$d ደቂቃዎች (እስከ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ድረስ)</item>
+ <item quantity="other">ለ%1$d ደቂቃዎች (እስከ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ድረስ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">ለ%1$d ሰዓቶች (እስከ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ድረስ)</item>
+ <item quantity="other">ለ%1$d ሰዓቶች (እስከ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ድረስ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">ለ%d ደቂቃዎች</item>
+ <item quantity="other">ለ%d ደቂቃዎች</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">ለ%d ሰዓቶች</item>
+ <item quantity="other">ለ%d ሰዓቶች</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"እስከ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ድረስ"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"ያለገደብ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ሰብስብ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 860b8a0..43355520 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -58,13 +58,17 @@
<string name="mismatchPin" msgid="609379054496863419">"أرقام التعريف الشخصية التي كتبتها غير مطابقة."</string>
<string name="invalidPin" msgid="3850018445187475377">"اكتب رقم تعريف شخصيًا مكونًا من 4 إلى ثمانية أعداد."</string>
<string name="invalidPuk" msgid="8761456210898036513">"اكتب رمز PUK مكونًا من 8 أرقام أو أكثر."</string>
- <string name="needPuk" msgid="919668385956251611">"بطاقة SIM مؤمّنة بكود PUK. اكتب كود PUK لإلغاء تأمينها."</string>
- <string name="needPuk2" msgid="4526033371987193070">"اكتب PUK2 لإلغاء تأمين بطاقة SIM."</string>
+ <string name="needPuk" msgid="919668385956251611">"شريحة SIM مؤمّنة بكود PUK. اكتب كود PUK لإلغاء تأمينها."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"اكتب PUK2 لإلغاء تأمين شريحة SIM."</string>
<string name="enablePin" msgid="209412020907207950">"محاولة غير ناجحة، مكّن قفل SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"يتبقى لديك محاولة واحدة (<xliff:g id="NUMBER">%d</xliff:g>) يتم بعدها قفل بطاقة SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"يتبقى لديك <xliff:g id="NUMBER">%d</xliff:g> من المحاولات يتم بعدها قفل بطاقة SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="zero">لم يتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدها قفل شريحة SIM.</item>
+ <item quantity="two">يتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>) يتم بعدهما قفل شريحة SIM.</item>
+ <item quantity="few">يتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات يتم بعدها قفل شريحة SIM.</item>
+ <item quantity="many">يتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة يتم بعدها قفل شريحة SIM.</item>
+ <item quantity="other">يتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات يتم بعدها قفل شريحة SIM.</item>
+ <item quantity="one">يتبقى لديك محاولة واحدة (<xliff:g id="NUMBER_0">%d</xliff:g>) يتم بعدها قفل شريحة SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"معرف المتصل الوارد"</string>
@@ -303,13 +307,13 @@
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"إرسال أحداث يتم الرد عليها عبر رسالة"</string>
<string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"السماح للتطبيق بإرسال طلبات إلى تطبيقات المراسلة الأخرى للتعامل مع الأحداث التي يتم الرد عليها عبر الرسائل في المكالمات الواردة."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"قراءة الرسائل النصية (الرسائل القصيرة SMS أو رسائل الوسائط المتعددة)"</string>
- <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على الجهاز اللوحي أو على بطاقة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة SMS، بغض النظر عن المحتوى أو مدى السرية."</string>
- <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"يتيح للتطبيق قراءة الرسائل القصيرة SMS المخزنة في التلفزيون أو في بطاقة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة، بغض النظر عن المحتوى ومدى السرية."</string>
- <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على هاتفك أو على بطاقة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة SMS، بغض النظر عن المحتوى أو مدى السرية."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على الجهاز اللوحي أو على شريحة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة SMS، بغض النظر عن المحتوى أو مدى السرية."</string>
+ <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"يتيح للتطبيق قراءة الرسائل القصيرة SMS المخزنة في التلفزيون أو في شريحة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة، بغض النظر عن المحتوى ومدى السرية."</string>
+ <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على هاتفك أو على شريحة SIM. ويتيح هذا للتطبيق قراءة جميع الرسائل القصيرة SMS، بغض النظر عن المحتوى أو مدى السرية."</string>
<string name="permlab_writeSms" msgid="3216950472636214774">"تعديل الرسائل النصية (الرسائل القصيرة SMS أو رسائل الوسائط المتعددة)"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة على الجهاز اللوحي أو بطاقة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
- <string name="permdesc_writeSms" product="tv" msgid="955871498983538187">"يتيح للتطبيق كتابة رسائل قصيرة SMS مخزنة على التلفزيون أو بطاقة SIM. وقد تؤدي التطبيقات الضارة إلى حذف رسائلك."</string>
- <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة على الهاتف أو بطاقة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة على الجهاز اللوحي أو شريحة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
+ <string name="permdesc_writeSms" product="tv" msgid="955871498983538187">"يتيح للتطبيق كتابة رسائل قصيرة SMS مخزنة على التلفزيون أو شريحة SIM. وقد تؤدي التطبيقات الضارة إلى حذف رسائلك."</string>
+ <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة على الهاتف أو شريحة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"تلقي رسائل نصية (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. ويتضمن هذا الإذن إمكانية مراقبة الرسائل التي يتم إرسالها إليك أو حذفها بدون عرضها لك."</string>
<string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"تلقي رسائل بلوتوث (MAP)"</string>
@@ -575,7 +579,7 @@
<string name="permlab_recordAudio" msgid="3876049771427466323">"تسجيل الصوت"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"للسماح للتطبيق بتسجيل الصوت باستخدام الميكروفون. ويتيح هذا الإذن للتطبيق تسجيل الصوت في أي وقت وبدون موافقة منك."</string>
<string name="permlab_sim_communication" msgid="1180265879464893029">"اتصالات SIM"</string>
- <string name="permdesc_sim_communication" msgid="5725159654279639498">"السماح للتطبيق بإرسال أوامر إلى بطاقة SIM. وهذا أمر بالغ الخطورة."</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"السماح للتطبيق بإرسال أوامر إلى شريحة SIM. وهذا أمر بالغ الخطورة."</string>
<string name="permlab_camera" msgid="3616391919559751192">"التقاط صور ومقاطع فيديو"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"للسماح للتطبيق بالتقاط صور ومقاطع فيديو من خلال الكاميرا. ويتيح هذا الإذن للتطبيق استخدام الكاميرا في أي وقت وبدون موافقة منك."</string>
<string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"تعطيل مؤشر LED للإرسال عندما تكون الكاميرا قيد الاستخدام"</string>
@@ -971,14 +975,14 @@
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"أعد المحاولة"</string>
<string name="lockscreen_password_wrong" msgid="5737815393253165301">"أعد المحاولة"</string>
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string>
- <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ليست هناك بطاقة SIM"</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
- <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"لا تتوفر بطاقة SIM في التلفزيون."</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"أدخل بطاقة SIM."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"بطاقة SIM مفقودة أو غير قابلة للقراءة. أدخل بطاقة SIM."</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"بطاقة SIM غير قابلة للاستخدام."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"تم تعطيل بطاقة SIM بشكل دائم.\n اتصل بمقدم خدمة اللاسلكي للحصول على بطاقة SIM أخرى."</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ليست هناك شريحة SIM"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك شريحة SIM في الجهاز اللوحي."</string>
+ <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"لا تتوفر شريحة SIM في التلفزيون."</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك شريحة SIM في الهاتف."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"أدخل شريحة SIM."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"شريحة SIM مفقودة أو غير قابلة للقراءة. أدخل شريحة SIM."</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"شريحة SIM غير قابلة للاستخدام."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"تم تعطيل شريحة SIM بشكل دائم.\n اتصل بمقدم خدمة اللاسلكي للحصول على شريحة SIM أخرى."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"المقطع الصوتي السابق"</string>
<string name="lockscreen_transport_next_description" msgid="573285210424377338">"المقطع الصوتي التالي"</string>
<string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"إيقاف مؤقت"</string>
@@ -988,10 +992,10 @@
<string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"تقديم سريع"</string>
<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">"بطاقة SIM مؤمّنة بكود PUK."</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"شريحة SIM مؤمّنة بكود PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"راجع دليل المستخدم أو اتصل بخدمة العملاء."</string>
- <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"بطاقة SIM مؤمّنة."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"شريحة SIM مؤمّنة."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"جارٍ إلغاء تأمين شريحة SIM…"</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة.\n\nالرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"لقد كتبت كلمة المرور <xliff:g id="NUMBER_0">%d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"لقد كتبت رمز PIN <xliff:g id="NUMBER_0">%d</xliff:g> مرة بشكل غير صحيح. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
@@ -1131,73 +1135,16 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"يريد <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> تمكين ميزة Explore by Touch. عند تشغيل ميزة Explore by Touch، سيكون بإمكانك سماع أو مشاهدة أوصاف لما تحت إصبعك أو إجراء إيماءات للتفاعل مع الهاتف."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"قبل شهر واحد"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل شهر واحد"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"قبل ثانية واحدة"</item>
- <item quantity="other" msgid="3903706804349556379">"قبل <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"قبل دقيقة واحدة"</item>
- <item quantity="other" msgid="2176942008915455116">"قبل <xliff:g id="COUNT">%d</xliff:g> دقيقة"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"قبل ساعة واحدة"</item>
- <item quantity="other" msgid="2467273239587587569">"قبل <xliff:g id="COUNT">%d</xliff:g> ساعات"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="zero">آخر <xliff:g id="COUNT_1">%d</xliff:g> من الأيام</item>
+ <item quantity="two">آخر يومين (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+ <item quantity="few">آخر <xliff:g id="COUNT_1">%d</xliff:g> أيام</item>
+ <item quantity="many">آخر <xliff:g id="COUNT_1">%d</xliff:g> يومًا</item>
+ <item quantity="other">آخر <xliff:g id="COUNT_1">%d</xliff:g> من الأيام</item>
+ <item quantity="one">آخر <xliff:g id="COUNT_0">%d</xliff:g> يوم</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"الشهر الماضي"</string>
<string name="older" msgid="5211975022815554840">"أقدم"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"أمس"</item>
- <item quantity="other" msgid="2479586466153314633">"قبل <xliff:g id="COUNT">%d</xliff:g> يوم"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"في ثانية واحدة"</item>
- <item quantity="other" msgid="1241926116443974687">"في <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"في دقيقة واحدة"</item>
- <item quantity="other" msgid="3330713936399448749">"في <xliff:g id="COUNT">%d</xliff:g> دقيقة"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"في ساعة واحدة"</item>
- <item quantity="other" msgid="547290677353727389">"في <xliff:g id="COUNT">%d</xliff:g> ساعة"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"غدًا"</item>
- <item quantity="other" msgid="5109449375100953247">"في <xliff:g id="COUNT">%d</xliff:g> يوم"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"قبل ثانية واحدة"</item>
- <item quantity="other" msgid="3699169366650930415">"قبل <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"قبل دقيقة واحدة"</item>
- <item quantity="other" msgid="851164968597150710">"قبل <xliff:g id="COUNT">%d</xliff:g> دقيقة"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"قبل ساعة واحدة"</item>
- <item quantity="other" msgid="6889970745748538901">"قبل <xliff:g id="COUNT">%d</xliff:g> ساعة"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"أمس"</item>
- <item quantity="other" msgid="3453342639616481191">"قبل <xliff:g id="COUNT">%d</xliff:g> يوم"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"في ثانية واحدة"</item>
- <item quantity="other" msgid="5495880108825805108">"في <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"في دقيقة واحدة"</item>
- <item quantity="other" msgid="4216113292706568726">"في <xliff:g id="COUNT">%d</xliff:g> دقيقة"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"في ساعة واحدة"</item>
- <item quantity="other" msgid="3705373766798013406">"في <xliff:g id="COUNT">%d</xliff:g> ساعة"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"غدًا"</item>
- <item quantity="other" msgid="2973062968038355991">"في <xliff:g id="COUNT">%d</xliff:g> يوم"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"في <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"في الساعة <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"في <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1160,30 @@
<string name="weeks" msgid="6509623834583944518">"أسابيع"</string>
<string name="year" msgid="4001118221013892076">"سنة"</string>
<string name="years" msgid="6881577717993213522">"أعوام"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"ثانية واحدة"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> من الثواني"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"دقيقة واحدة"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> من الدقائق"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"ساعة واحدة"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> من الساعات"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="zero">أقل من ثانية (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="two">ثانيتان (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> ثوانٍ</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> ثانية</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الثواني</item>
+ <item quantity="one">ثانية واحدة</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="zero">أقل من دقيقة (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="two">دقيقتان (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> دقائق</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> دقيقة</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الدقائق</item>
+ <item quantity="one">دقيقة واحدة</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="zero">أقل من ساعة (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="two">ساعتان (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> ساعات</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> ساعة</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> من الساعات</item>
+ <item quantity="one">ساعة واحدة</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>
@@ -1333,14 +1292,22 @@
<string name="ringtone_silent" msgid="7937634392408977062">"لا شيء"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"نغمات الرنين"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"نغمة رنين غير معروفة"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"شبكة Wi-Fi متاحة"</item>
- <item quantity="other" msgid="4192424489168397386">"شبكات Wi-Fi متاحة"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"هناك شبكة Wi-Fi مفتوحة متاحة"</item>
- <item quantity="other" msgid="7915895323644292768">"هناك شبكات Wi-Fi مفتوحة متاحة"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="zero">لا تتوفر أية شبكات Wi-Fi</item>
+ <item quantity="two">تتوفر شبكتا Wi-Fi</item>
+ <item quantity="few">تتوفر شبكات Wi-Fi</item>
+ <item quantity="many">تتوفر شبكات Wi-Fi</item>
+ <item quantity="other">تتوفر شبكات Wi-Fi</item>
+ <item quantity="one">تتوفر شبكة Wi-Fi واحدة</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="zero">لا تتوفر أية شبكات Wi-Fi مفتوحة</item>
+ <item quantity="two">تتوفر شبكتا Wi-Fi مفتوحتان</item>
+ <item quantity="few">تتوفر شبكات Wi-Fi مفتوحة</item>
+ <item quantity="many">تتوفر شبكات Wi-Fi مفتوحة</item>
+ <item quantity="other">تتوفر شبكات Wi-Fi مفتوحة</item>
+ <item quantity="one">تتوفر شبكة Wi-Fi واحدة مفتوحة</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"تسجيل الدخول إلى شبكة Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"تسجيل الدخول إلى الشبكة"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1380,10 +1347,10 @@
<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>
- <string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة بطاقة SIM"</string>
- <string name="sim_removed_message" msgid="5450336489923274918">"لن تكون شبكة الجوّال متوفرة إلى أن تعيد تشغيل الهاتف مع إدخال بطاقة SIM صالحة."</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة شريحة SIM"</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"لن تكون شبكة الجوّال متوفرة إلى أن تعيد تشغيل الهاتف مع إدخال شريحة SIM صالحة."</string>
<string name="sim_done_button" msgid="827949989369963775">"تم"</string>
- <string name="sim_added_title" msgid="3719670512889674693">"تمت إضافة بطاقة SIM"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"تمت إضافة شريحة SIM"</string>
<string name="sim_added_message" msgid="7797975656153714319">"أعد تشغيل جهازك للدخول إلى شبكة الجوّال."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"إعادة التشغيل"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string>
@@ -1416,6 +1383,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"موافق"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"التوصيل كجهاز وسائط"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"التوصيل ككاميرا"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"تم التوصيل كجهاز MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"التوصيل كأداة تثبيت"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"الاتصال بجهاز USB ملحق"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"المس للاطلاع على خيارات USB الأخرى."</string>
@@ -1531,10 +1499,14 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"مطابقة واحدة"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="zero"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="two"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">مباراة واحدة</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"تم"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"جارٍ إلغاء تحميل وحدة تخزين USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"جارٍ إلغاء تحميل بطاقة SD..."</string>
@@ -1680,14 +1652,14 @@
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"أدخل رمز PIN لبطاقة SIM"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رمز PIN"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"أدخل كلمة المرور"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"بطاقة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"شريحة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رمز PIN المراد"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين شريحة SIM…"</string>
<string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رمز PIN غير صحيح."</string>
<string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
<string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"يجب أن يتكون رمز PUK من 8 أرقام."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل بطاقة SIM نهائيًا."</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل شريحة SIM نهائيًا."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"لإلغاء التأمين، سجّل الدخول بحسابك في Google."</string>
@@ -1820,10 +1792,14 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"إنشاء رقم تعريف شخصي لتعديل القيود"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"أرقام التعريف الشخصية لا تتطابق، أعد المحاولة."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"رمز PIN أقصر مما يلزم، يجب ألا يقل عن 4 أرقام. "</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"أعد المحاولة خلال ثانية واحدة."</item>
- <item quantity="other" msgid="4730868920742952817">"أعد المحاولة خلال <xliff:g id="COUNT">%d</xliff:g> ثانية"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="zero">حاول مرة أخرى خلال أقل من ثانية <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="two">حاول مرة أخرى خلال ثانيتين (<xliff:g id="COUNT">%d</xliff:g>)</item>
+ <item quantity="few">حاول مرة أخرى خلال <xliff:g id="COUNT">%d</xliff:g> ثوانٍ</item>
+ <item quantity="many">حاول مرة أخرى خلال <xliff:g id="COUNT">%d</xliff:g> ثانية</item>
+ <item quantity="other">حاول مرة أخرى خلال <xliff:g id="COUNT">%d</xliff:g> من الثواني</item>
+ <item quantity="one">حاول مرة أخرى خلال ثانية واحدة</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"أعد المحاولة لاحقًا"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"مرر بسرعة من أعلى لأسفل للخروج من وضع ملء الشاشة."</string>
<string name="done_label" msgid="2093726099505892398">"تم"</string>
@@ -1849,22 +1825,38 @@
<string name="battery_saver_description" msgid="1960431123816253034">"للمساعدة في تحسين عمر البطارية، يساعد موفر البطارية في تقليل أداء الجهاز ويفرض قيدًا على الاهتزاز وخدمات الموقع ومعظم بيانات الخلفية. قد لا يتم تحديث البريد الإلكتروني والمراسلة والتطبيقات الأخرى التي تعتمد على المزامنة ما لم تفتحها.\n\nيتم إيقاف موفر البطارية تلقائيًا أثناء شحن الجهاز."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"إلى أن ينتهي وقت التوقف عن العمل في <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"حتى انتهاء وقت التعطل"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"لمدة دقيقة واحدة (حتى <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"لمدة %1$d من الدقائق (حتى <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"لمدة ساعة واحدة (حتى <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"لمدة %1$d من الساعات (حتى <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"لمدة دقيقة واحدة"</item>
- <item quantity="other" msgid="6924190729213550991">"لمدة %d من الدقائق"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"لمدة ساعة واحدة"</item>
- <item quantity="other" msgid="5408537517529822157">"لمدة %d من الساعات"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="zero">لمدة أقل من دقيقة (%1$d) (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="two">لمدة دقيقتين (%1$d) (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">لمدة %1$d دقائق (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">لمدة %1$d دقيقة (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">لمدة %1$d من الدقائق (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">لمدة دقيقة واحدة (حتى <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="zero">لمدة أقل من ساعة (%1$d) (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="two">لمدة ساعتين (%1$d) (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">لمدة %1$d ساعات (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">لمدة %1$d ساعة (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">لمدة %1$d من الساعات (حتى <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">لمدة ساعة واحدة (حتى <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="zero">لمدة أقل من دقيقة (%d)</item>
+ <item quantity="two">لمدة دقيقتين (%d)</item>
+ <item quantity="few">لمدة %d دقائق</item>
+ <item quantity="many">لمدة %d دقيقة</item>
+ <item quantity="other">لمدة %d من الدقائق</item>
+ <item quantity="one">لمدة دقيقة واحدة</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="zero">لمدة أقل من ساعة (%d)</item>
+ <item quantity="two">لمدة ساعتين (%d)</item>
+ <item quantity="few">لمدة %d ساعات</item>
+ <item quantity="many">لمدة %d ساعة</item>
+ <item quantity="other">لمدة %d من الساعات</item>
+ <item quantity="one">لمدة ساعة واحدة</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"حتى <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"إلى أجل غير مسمى"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"تصغير"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 479cfcf..b22eb7a 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -967,75 +967,11 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> Toxunaraq Kəşf Et rejimini aktivləşdirmək istəyir. Toxunaraq Kəşf Et açıldığı zaman, barmağınızın altında nə olduğu haqda olan təsvirləri eşidə və ya görə bilərsiniz və ya telefonda insanlarla əlaqəyə keçmək üçün jestlər həyata keçirə bilərsiniz"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 ay öncə"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 ay əvvəl"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 saniyə əvvəl"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> saniyə əvvəl"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 dəqiqə əvvəl"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> dəqiqə əvvəl"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 saat əvvəl"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> saat əvvəl"</item>
- </plurals>
<plurals name="last_num_days">
<item quantity="other" msgid="3069992808164318268">"Son <xliff:g id="COUNT">%d</xliff:g> gün"</item>
</plurals>
<string name="last_month" msgid="3959346739979055432">"Keçən ay"</string>
<string name="older" msgid="5211975022815554840">"Köhnə"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"dünən"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> gün əvvəl"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 saniyə ərzində"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> saniyə içində"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 dəqiqə içində"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> dəqiqə ərzində"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 saata"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> saata"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"sabah"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> gün ərzində"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 saniyə əvvəl"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> san əvvəl"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 dəqiqə əvvəl"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> dəqiqə əvvəl"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 saat əvvəl"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> saat əvvəl"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"dünən"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> gün əvvəl"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 san ərzində"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> san ərzində"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 dəq ərzində"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> dəqiqəyə"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 saat ərzində"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> saata"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"sabah"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> günə"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> tarixində"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"saat <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> ilində"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 9f572cf..ce2aa9a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM картата ви е заключена с PUK. Въведете PUK кода, за да я отключите."</string>
<string name="needPuk2" msgid="4526033371987193070">"Въведете PUK2, за да отблокирате SIM картата."</string>
<string name="enablePin" msgid="209412020907207950">"Неуспешно – активирайте заключването на SIM/RUIM картата."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Остава ви <xliff:g id="NUMBER">%d</xliff:g> опит, преди SIM картата да бъде заключена."</item>
- <item quantity="other" msgid="7530597808358774740">"Остават ви <xliff:g id="NUMBER">%d</xliff:g> опита, преди SIM картата да бъде заключена."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Остават ви <xliff:g id="NUMBER_1">%d</xliff:g> опита, преди SIM картата да бъде заключена.</item>
+ <item quantity="one">Остава ви <xliff:g id="NUMBER_0">%d</xliff:g> опит, преди SIM картата да бъде заключена.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Идентификация на вх. обаждания"</string>
@@ -1131,73 +1131,12 @@
<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">"Преди повече от месец"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Преди 1 секунда"</item>
- <item quantity="other" msgid="3903706804349556379">"Преди <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Преди 1 минута"</item>
- <item quantity="other" msgid="2176942008915455116">"Преди <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Преди 1 час"</item>
- <item quantity="other" msgid="2467273239587587569">"Преди <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Последните <xliff:g id="COUNT_1">%d</xliff:g> дни</item>
+ <item quantity="one">Последният <xliff:g id="COUNT_0">%d</xliff:g> ден</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Последният месец"</string>
<string name="older" msgid="5211975022815554840">"По-стари"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"вчера"</item>
- <item quantity="other" msgid="2479586466153314633">"Преди <xliff:g id="COUNT">%d</xliff:g> дни"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"след 1 секунда"</item>
- <item quantity="other" msgid="1241926116443974687">"след <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"след 1 минута"</item>
- <item quantity="other" msgid="3330713936399448749">"след <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"след 1 час"</item>
- <item quantity="other" msgid="547290677353727389">"след <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"утре"</item>
- <item quantity="other" msgid="5109449375100953247">"след <xliff:g id="COUNT">%d</xliff:g> дни"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Преди 1 сек"</item>
- <item quantity="other" msgid="3699169366650930415">"Преди <xliff:g id="COUNT">%d</xliff:g> сек"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Преди 1 мин"</item>
- <item quantity="other" msgid="851164968597150710">"Преди <xliff:g id="COUNT">%d</xliff:g> мин"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Преди 1 час"</item>
- <item quantity="other" msgid="6889970745748538901">"Преди <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"вчера"</item>
- <item quantity="other" msgid="3453342639616481191">"Преди <xliff:g id="COUNT">%d</xliff:g> дни"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"след 1 сек"</item>
- <item quantity="other" msgid="5495880108825805108">"след <xliff:g id="COUNT">%d</xliff:g> сек"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"след 1 мин"</item>
- <item quantity="other" msgid="4216113292706568726">"след <xliff:g id="COUNT">%d</xliff:g> мин"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"след 1 час"</item>
- <item quantity="other" msgid="3705373766798013406">"след <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"утре"</item>
- <item quantity="other" msgid="2973062968038355991">"след <xliff:g id="COUNT">%d</xliff:g> дни"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"на <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"през <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"седмици"</string>
<string name="year" msgid="4001118221013892076">"година"</string>
<string name="years" msgid="6881577717993213522">"години"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 минута"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 час"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ <item quantity="one">1 секунда</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минути</item>
+ <item quantity="one">1 минута</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> часа</item>
+ <item quantity="one">1 час</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Без"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестна мелодия"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Има достъпна Wi-Fi мрежа"</item>
- <item quantity="other" msgid="4192424489168397386">"Има достъпни Wi-Fi мрежи"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Има достъпна отворена Wi-Fi мрежа"</item>
- <item quantity="other" msgid="7915895323644292768">"Има достъпни отворени Wi-Fi мрежи"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Има достъпни Wi-Fi мрежи</item>
+ <item quantity="one">Има достъпна Wi-Fi мрежа</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Има достъпни отворени Wi-Fi мрежи</item>
+ <item quantity="one">Има достъпна отворена Wi-Fi мрежа</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Влизане в Wi-Fi мрежа"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Влезте в мрежата"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Свързан като медийно устройство"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Свързан като камера"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Свързано като MIDI устройство"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Свързан като инсталационна програма"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Установена е връзка с аксесоар за USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Докоснете за други опции за USB."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 съответствие"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> от <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> от <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 игра</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB хранилището се спира..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD картата се спира..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Създаване на ПИН код за промяна на ограниченията"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"ПИН кодовете не са идентични. Опитайте отново."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"ПИН кодът е твърде кратък. Трябва да е поне 4 цифри."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Опитайте отново след 1 секунда"</item>
- <item quantity="other" msgid="4730868920742952817">"Опитайте отново след <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Опитайте отново след <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ <item quantity="one">Опитайте отново след 1 секунда</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Опитайте отново по-късно"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"За изход от цял екран прекарайте пръст отгоре надолу."</string>
<string name="done_label" msgid="2093726099505892398">"Готово"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"С цел удължаване на живота на батерията режимът за запазването й намалява ефективността на устройството ви и ограничава вибрирането, услугите за местоположение и повечето данни на заден план. Приложенията за електронна поща, съобщения и др., които разчитат на синхронизиране, може да не се актуализират, освен ако не ги отворите.\n\nРежимът за запазване на батерията се изключва автоматично, когато устройството ви се зарежда."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"До приключване на неактивността в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"До приключването на почивката ви"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"За една минута (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"За %1$d минути (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"За един час (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"За %1$d часа (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"За една минута"</item>
- <item quantity="other" msgid="6924190729213550991">"За %d минути"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"За един час"</item>
- <item quantity="other" msgid="5408537517529822157">"За %d часа"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">За %1$d минути (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">За една минута (до <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">За %1$d часа (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">За един час (до <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">За %d минути</item>
+ <item quantity="one">За една минута</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">За %d часа</item>
+ <item quantity="one">За един час</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"За неопределено време"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Свиване"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 9f79384..4afa0a3 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"আপনার সিম কার্ডটি PUK-কোড দিয়ে লক করা রয়েছে৷ এটিকে আনলক করতে PUK কোডটি লিখুন৷"</string>
<string name="needPuk2" msgid="4526033371987193070">"সিম কার্ড অবরোধ মুক্ত করতে PUK2 লিখুন৷"</string>
<string name="enablePin" msgid="209412020907207950">"অসফল, সিম/RUIM লক সক্ষম করুন৷"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷"</item>
- <item quantity="other" msgid="7530597808358774740">"আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম লক হয়ে যাবে৷"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
+ <item quantity="other">আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM লক হয়ে যাবে৷</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"আগত কলার ID"</string>
@@ -1131,73 +1131,12 @@
<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">"১ মাস আগে"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"১ মাস আগে"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"১ সেকেন্ড আগে"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ড আগে"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"১ মিনিট আগে"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> মিনিট আগে"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"১ ঘন্টা আগে"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টা আগে"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">বিগত <xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+ <item quantity="other">বিগত <xliff:g id="COUNT_1">%d</xliff:g> দিন</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"গত মাস"</string>
<string name="older" msgid="5211975022815554840">"পুরোনো"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"গতকাল"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> দিন আগে"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"১ সেকেন্ডের মধ্যে"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ডের মধ্যে"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"১ মিনিটের মধ্যে"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> মিনিটের মধ্যে"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"১ ঘন্টার মধ্যে"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টার মধ্যে"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"আগামীকাল"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> দিনের মধ্যে"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"১ সেকেন্ড আগে"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ড আগে"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"১ মিনিট আগে"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> মিনিট আগে"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"১ ঘন্টা আগে"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টা আগে"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"গতকাল"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> দিন আগে"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"১ সেকেন্ডের মধ্যে"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ডের মধ্যে"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"১ মিনিটের মধ্যে"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> মিনিটের মধ্যে"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"১ ঘন্টার মধ্যে"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টার মধ্যে"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"আগামীকাল"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> দিনের মধ্যে"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> এ"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> এ"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> এ"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"সপ্তাহ"</string>
<string name="year" msgid="4001118221013892076">"বছর"</string>
<string name="years" msgid="6881577717993213522">"বছর"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"১ সেকেন্ড"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ড"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"১ মিনিট"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> মিনিট"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"১ ঘন্টা"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ঘন্টা"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> সেকেন্ড</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> সেকেন্ড</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> মিনিট</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> মিনিট</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ঘন্টা</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"কোনো কিছুই নয়"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"রিংটোনগুলি"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"অজানা রিংটোন"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi নেটওয়ার্ক উপলব্ধ রয়েছে"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi নেটওয়ার্ক উপলব্ধ রয়েছে"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"খোলা Wi-Fi নেটওয়ার্ক উপলব্ধ রয়েছে"</item>
- <item quantity="other" msgid="7915895323644292768">"খোলা Wi-Fi নেটওয়ার্ক উপলব্ধ রয়েছে"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Wi-Fi নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
+ <item quantity="other">Wi-Fi নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">খোলা Wi-Fi নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
+ <item quantity="other">খোলা Wi-Fi নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi নেটওয়ার্কে সাইন ইন করুন"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"নেটওয়ার্কে সাইন ইন করুন"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ঠিক আছে"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"একটি মিডিয়া ডিভাইস হিসাবে সংযুক্ত হয়েছে"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"একটি ক্যামেরা হিসাবে সংযুক্ত"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"একটি MIDI ডিভাইস হিসাবে সংযুক্ত করা হয়েছে"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"একটি ইনস্টলার হিসাবে সংযুক্ত হয়েছে"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"একটি USB যন্ত্রাংশতে সংযুক্ত হয়েছে"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"অন্যন্য USB বিকল্পের জন্য স্পর্শ করুন৷"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"১টি সমরূপ"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>টির মধ্যে <xliff:g id="INDEX">%d</xliff:g> নম্বর"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g>টির <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>টির <xliff:g id="INDEX">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"সম্পন্ন হয়েছে"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB সংগ্রহস্থল আনমাউন্ট করা হচ্ছে…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD কার্ড আনমাউন্ট করা হচ্ছে…"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN খুবই ছোট৷ এটিকে কমপক্ষে ৪ সংখ্যার হতে হবে৷"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"১ সেকেন্ডের মধ্যে আবার চেষ্টা করুন"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"পরে আবার চেষ্টা করুন"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"পূর্ণস্ক্রীণ থেকে প্রস্থান করতে উপর থেকে নীচের দিকে সোয়াইপ করুন৷"</string>
<string name="done_label" msgid="2093726099505892398">"সম্পন্ন হয়েছে"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ব্যাটরির লাইফ উন্নত করতে সহায়তা করতে, ব্যাটারি সাশ্রয়কারী আপনার ডিভাইসের কার্যসম্পাদনা হ্রাস করে এবং কম্পন, অবস্থান পরিষেবাসমূহ এবং অধিকাংশ ব্যাকগ্রাউন্ড ডেটা সীমিত করে৷ ইমেল, বার্তাপ্রেরণ এবং অন্যান্য অ্যাপ্লিকেশানগুলিকে যেগুলি সিঙ্কের উপর নির্ভর করে সেগুলিকে আপনি না খোলা পর্যন্ত নাও আপডেট হতে পারে৷\n\nআপনার ডিভাইসটিকে যখন চার্জ করা হয় তখন ব্যাটারি সাশ্রয়কারী স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়৷"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>টার সময়ে আপনার ডাউনটাইম শেষ হওয়া পর্যন্ত"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"আপনার ডাউনটাইম শেষ না হওয়া পর্যন্ত"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"এক মিনিটের জন্য (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> পর্যন্ত)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d মিনিটের জন্য (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> পর্যন্ত)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"এক ঘন্টার জন্য (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> পর্যন্ত)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d ঘন্টার জন্য (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> পর্যন্ত)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"এক মিনিটের জন্য"</item>
- <item quantity="other" msgid="6924190729213550991">"%d মিনিটের জন্য"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"এক ঘন্টার জন্য"</item>
- <item quantity="other" msgid="5408537517529822157">"%d ঘন্টার জন্য"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d মিনিটের জন্য (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পর্যন্ত)</item>
+ <item quantity="other">%1$d মিনিটের জন্য (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পর্যন্ত)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d ঘন্টার জন্য (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পর্যন্ত)</item>
+ <item quantity="other">%1$d ঘন্টার জন্য (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> পর্যন্ত)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d মিনিটের জন্য</item>
+ <item quantity="other">%d মিনিটের জন্য</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d ঘন্টার জন্য</item>
+ <item quantity="other">%d ঘন্টার জন্য</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"অনির্দিষ্টভাবে"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"সঙ্কুচিত করুন"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 3f68244..63365bb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"La targeta SIM està bloquejada pel PUK. Escriviu el codi PUK per desbloquejar-la."</string>
<string name="needPuk2" msgid="4526033371987193070">"Escriviu el PUK2 per desbloquejar la targeta SIM."</string>
<string name="enablePin" msgid="209412020907207950">"No és correcte; activa el bloqueig de RUIM/SIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Et queda <xliff:g id="NUMBER">%d</xliff:g> intent; si no l\'encertes, la SIM es bloquejarà."</item>
- <item quantity="other" msgid="7530597808358774740">"Et queden <xliff:g id="NUMBER">%d</xliff:g> intents; si no l\'encertes, la SIM es bloquejarà."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents; si no l\'encertes, la SIM es bloquejarà.</item>
+ <item quantity="one">Et queda <xliff:g id="NUMBER_0">%d</xliff:g> intent; si no l\'encertes, la SIM es bloquejarà.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identificació de trucada entrant"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vol activar l\'exploració tàctil. Quan l\'exploració per tàctil està activada, pots escoltar o veure les descripcions del contingut seleccionat o utilitzar gestos per interactuar amb el telèfon."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Fa 1 mes"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Fa més d\'1 mes"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Fa 1 segon"</item>
- <item quantity="other" msgid="3903706804349556379">"Fa <xliff:g id="COUNT">%d</xliff:g> segons"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Fa 1 minut"</item>
- <item quantity="other" msgid="2176942008915455116">"Fa <xliff:g id="COUNT">%d</xliff:g> minuts"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Fa 1 hora"</item>
- <item quantity="other" msgid="2467273239587587569">"Fa <xliff:g id="COUNT">%d</xliff:g> hores"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Darrers <xliff:g id="COUNT_1">%d</xliff:g> dies</item>
+ <item quantity="one">Darrer dia (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"El mes passat"</string>
<string name="older" msgid="5211975022815554840">"Més antigues"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"Ahir"</item>
- <item quantity="other" msgid="2479586466153314633">"Fa <xliff:g id="COUNT">%d</xliff:g> dies"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"d\'aquí a 1 segon"</item>
- <item quantity="other" msgid="1241926116443974687">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> segons"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"d\'aquí a 1 minut"</item>
- <item quantity="other" msgid="3330713936399448749">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> minuts"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"d\'aquí a 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> hores"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"demà"</item>
- <item quantity="other" msgid="5109449375100953247">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> dies"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Fa 1 s"</item>
- <item quantity="other" msgid="3699169366650930415">"Fa <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"fa 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"Fa <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Fa 1 hora"</item>
- <item quantity="other" msgid="6889970745748538901">"Fa <xliff:g id="COUNT">%d</xliff:g> hores"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ahir"</item>
- <item quantity="other" msgid="3453342639616481191">"Fa <xliff:g id="COUNT">%d</xliff:g> dies"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"d\'aquí a 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"d\'aquí a 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> minuts"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"d\'aquí a 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> hores"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"demà"</item>
- <item quantity="other" msgid="2973062968038355991">"d\'aquí a <xliff:g id="COUNT">%d</xliff:g> dies"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"el <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"a les <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"el <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"setmanes"</string>
<string name="year" msgid="4001118221013892076">"any"</string>
<string name="years" msgid="6881577717993213522">"anys"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segon"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segons"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuts"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hores"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segons</item>
+ <item quantity="one">1 segon</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuts</item>
+ <item quantity="one">1 minut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hores</item>
+ <item quantity="one">1 hora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema amb el vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Aquest vídeo no és vàlid per a la reproducció en aquest dispositiu."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No es pot reproduir aquest vídeo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Cap"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sons"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"To desconegut"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Xarxa Wi-fi disponible"</item>
- <item quantity="other" msgid="4192424489168397386">"Xarxes Wi-fi disponibles"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Xarxa Wi-fi oberta disponible"</item>
- <item quantity="other" msgid="7915895323644292768">"Xarxes Wi-fi obertes disponibles"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Xarxes Wi-Fi disponibles</item>
+ <item quantity="one">Xarxa Wi-Fi disponible</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Xarxes Wi-Fi obertes disponibles</item>
+ <item quantity="one">Xarxa Wi-Fi oberta disponible</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Inicia la sessió a la xarxa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Inicia la sessió a la xarxa"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a disp. multimèdia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connectat com a càmera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connectat com a dispositiu MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connectat com a instal·lador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connectat a un accessori USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toca per accedir a altres opcions d\'USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Omet"</string>
<string name="no_matches" msgid="8129421908915840737">"Cap coincidència"</string>
<string name="find_on_page" msgid="1946799233822820384">"Troba-ho a la pàgina"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 coincidència"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 partida</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Fet"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"S\'està desactivant l\'emmagatzematge USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"S\'està desactivant la targeta SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crea un pin per modificar les restriccions"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Els PIN no coincideixen. Torna-ho a provar."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"El PIN és massa curt. Ha de tenir quatre dígits com a mínim."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Torna-ho a provar d\'aquí a 1 segon"</item>
- <item quantity="other" msgid="4730868920742952817">"Torna-ho a provar d\'aquí a <xliff:g id="COUNT">%d</xliff:g> segons"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Torna-ho a provar d\'aquí a <xliff:g id="COUNT">%d</xliff:g> segons</item>
+ <item quantity="one">Torna-ho a provar d\'aquí a 1 segon</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Torna-ho a provar més tard"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Fes lliscar el dit cap avall per sortir de la pantalla completa."</string>
<string name="done_label" msgid="2093726099505892398">"Fet"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Per allargar la durada de la bateria, l\'estalvi de bateria redueix el rendiment del dispositiu i limita l\'ús de la vibració, dels serveis d\'ubicació i de la majoria de les dades en segon pla. És possible que el correu electrònic, la missatgeria i altres aplicacions que depenen de la sincronització no s\'actualitzin fins que els obris.\n\nL\'estalvi de bateria es desactiva de manera automàtica quan el dispositiu es posa a carregar."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Fins que no finalitzi la inactivitat a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>."</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Fins que finalitzi el temps d\'inactivitat"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Durant 1 minut (fins a les <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Durant %1$d minuts (fins a les <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Durant 1 hora (fins a les <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Durant %1$d hores (fins a les <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Durant un minut"</item>
- <item quantity="other" msgid="6924190729213550991">"Durant %d minuts"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Durant una hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Durant %d hores"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Durant %1$d minuts (fins a les <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durant 1 minut (fins a les <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Durant %1$d hores (fins a les <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durant 1 hora (fins a les <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Durant %d minuts</item>
+ <item quantity="one">Durant un minut</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Durant %d hores</item>
+ <item quantity="one">Durant 1 hora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidament"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Replega"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 5cd6802..3c75764 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"SIM karta je blokována pomocí kódu PUK. Odblokujete ji zadáním kódu PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Chcete-li odblokovat SIM kartu, zadejte kód PUK2."</string>
<string name="enablePin" msgid="209412020907207950">"Operace nebyla úspěšná, povolte zámek SIM/RUIM karty."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Máte ještě <xliff:g id="NUMBER">%d</xliff:g> pokus. Poté bude SIM karta uzamčena."</item>
- <item quantity="other" msgid="7530597808358774740">"Počet zbývajících pokusů, po jejichž vyčerpání bude SIM karta uzamčena: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="few">Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusy. Poté bude SIM karta uzamčena.</item>
+ <item quantity="many">Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusu. Poté bude SIM karta uzamčena.</item>
+ <item quantity="other">Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusů. Poté bude SIM karta uzamčena.</item>
+ <item quantity="one">Máte ještě <xliff:g id="NUMBER_0">%d</xliff:g> pokus. Poté bude SIM karta uzamčena.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Příchozí identifikace volajícího"</string>
@@ -1131,73 +1133,14 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Služba <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> požaduje povolení funkce Prozkoumání dotykem. Pokud je funkce Prozkoumání dotykem zapnuta, můžete slyšet nebo vidět popisy objektů pod vaším prstem nebo ovládat telefon gesty."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"před 1 měsícem"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Déle než před 1 měsícem"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"před 1 sekundou"</item>
- <item quantity="other" msgid="3903706804349556379">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"před 1 min"</item>
- <item quantity="other" msgid="2176942008915455116">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"před 1 h"</item>
- <item quantity="other" msgid="2467273239587587569">"před <xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="few">Poslední <xliff:g id="COUNT_1">%d</xliff:g> dny</item>
+ <item quantity="many">Posledních <xliff:g id="COUNT_1">%d</xliff:g> dne</item>
+ <item quantity="other">Posledních <xliff:g id="COUNT_1">%d</xliff:g> dnů</item>
+ <item quantity="one">Poslední <xliff:g id="COUNT_0">%d</xliff:g> den</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Poslední měsíc"</string>
<string name="older" msgid="5211975022815554840">"Starší"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"včera"</item>
- <item quantity="other" msgid="2479586466153314633">"před <xliff:g id="COUNT">%d</xliff:g> dny"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"za 1 sekundu"</item>
- <item quantity="other" msgid="1241926116443974687">"za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"za 1 minutu"</item>
- <item quantity="other" msgid="3330713936399448749">"za <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"za 1 hodinu"</item>
- <item quantity="other" msgid="547290677353727389">"za <xliff:g id="COUNT">%d</xliff:g> hod."</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"zítra"</item>
- <item quantity="other" msgid="5109449375100953247">"za <xliff:g id="COUNT">%d</xliff:g> dny"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"před 1 s"</item>
- <item quantity="other" msgid="3699169366650930415">"před <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"před 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"před <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"před 1 h"</item>
- <item quantity="other" msgid="6889970745748538901">"před <xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"včera"</item>
- <item quantity="other" msgid="3453342639616481191">"před <xliff:g id="COUNT">%d</xliff:g> dny"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"za 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"za 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"za <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"za 1 hodinu"</item>
- <item quantity="other" msgid="3705373766798013406">"za <xliff:g id="COUNT">%d</xliff:g> hod."</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"zítra"</item>
- <item quantity="other" msgid="2973062968038355991">"za <xliff:g id="COUNT">%d</xliff:g> dny"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"dne <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"v <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"roku <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"týd."</string>
<string name="year" msgid="4001118221013892076">"rokem"</string>
<string name="years" msgid="6881577717993213522">"lety"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hodina"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ <item quantity="one">1 sekunda</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minuty</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> minuty</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minut</item>
+ <item quantity="one">1 minuta</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="few">[<xliff:g id="COUNT">%d</xliff:g>] hodiny</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> hodiny</item>
+ <item quantity="other">[<xliff:g id="COUNT">%d</xliff:g>] hodin</item>
+ <item quantity="one">1 hodina</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Potíže s videem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Toto video nelze přenášet datovým proudem do tohoto zařízení."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Toto video nelze přehrát."</string>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Žádné"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváněcí tóny"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Neznámý vyzváněcí tón"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"K dispozici je síť Wi-Fi."</item>
- <item quantity="other" msgid="4192424489168397386">"Jsou k dispozici sítě Wi-Fi."</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"K dispozici je veřejná síť Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"Jsou k dispozici veřejné sítě Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="few">K dispozici jsou sítě Wi-Fi</item>
+ <item quantity="many">K dispozici jsou sítě Wi-Fi</item>
+ <item quantity="other">K dispozici jsou sítě Wi-Fi</item>
+ <item quantity="one">K dispozici je síť Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="few">K dispozici jsou veřejné sítě Wi-Fi</item>
+ <item quantity="many">K dispozici jsou veřejné sítě Wi-Fi</item>
+ <item quantity="other">K dispozici jsou veřejné sítě Wi-Fi</item>
+ <item quantity="one">K dispozici je veřejná síť Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Přihlásit se k síti Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Přihlášení k síti"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Připojeno jako mediální zařízení"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Připojeno jako fotoaparát"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Připojeno jako zařízení MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Připojeno jako instalátor"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Připojeno k perifernímu zařízení USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Dotykem zobrazíte další možnosti rozhraní USB."</string>
@@ -1531,10 +1485,12 @@
<string name="skip_button_label" msgid="1275362299471631819">"Přeskočit"</string>
<string name="no_matches" msgid="8129421908915840737">"Žádné shody"</string>
<string name="find_on_page" msgid="1946799233822820384">"Hledat na stránce"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 shoda"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> ze <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 shoda</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Hotovo"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Odpojování úložiště USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Odpojování karty SD..."</string>
@@ -1820,10 +1776,12 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Vytvořit kód PIN pro úpravy omezení"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Kódy PIN se neshodují. Zkuste to znovu."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Kód PIN je příliš krátký. Musí mít alespoň čtyři číslice."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Zkuste to znovu za 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Zkuste to znovu za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="few">Zkuste to znovu za <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many">Zkuste to znovu za <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="other">Zkuste to znovu za <xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ <item quantity="one">Zkuste to znovu za 1 sekundu</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Zkuste to znovu později"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Režim celé obrazovky ukončíte přejetím dolů."</string>
<string name="done_label" msgid="2093726099505892398">"Hotovo"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Spořič baterie za účelem prodloužení výdrže baterie snižuje výkon zařízení a omezuje vibrace, služby určování polohy a většinu dat na pozadí. E-mail, aplikace pro zasílání zpráv a další aplikace, které používají synchronizaci, se nemusejí aktualizovat, dokud je neotevřete.\n\nPři nabíjení zařízení se spořič baterie automaticky vypne."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dokud v <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí pozastavení"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Dokud neskončí výpadek"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Jednu minutu (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d min (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Jednu hodinu (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d h (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Na jednu minutu"</item>
- <item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Na 1 h"</item>
- <item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="few">%1$d minuty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d minuty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d minut (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Jednu minutu (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="few">%1$d hodiny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d hodiny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d hodin (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Jednu hodinu (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="few">%d minuty</item>
+ <item quantity="many">%d minuty</item>
+ <item quantity="other">%d minut</item>
+ <item quantity="one">Jednu minutu</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="few">%d hodiny</item>
+ <item quantity="many">%d hodiny</item>
+ <item quantity="other">%d hodin</item>
+ <item quantity="one">Jednu hodinu</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Na dobu neurčitou"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Sbalit"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 157d282..733b7a7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Dit SIM-kort er låst med PUK-koden. Indtast PUK-koden for at låse den op."</string>
<string name="needPuk2" msgid="4526033371987193070">"Indtast PUK2-koden for at låse op for SIM-kortet."</string>
<string name="enablePin" msgid="209412020907207950">"Mislykkedes. Aktivér SIM-/RUIM-lås."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver låst."</item>
- <item quantity="other" msgid="7530597808358774740">"Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver låst."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver låst.</item>
+ <item quantity="other">Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver låst.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI-nummer"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Indgående opkalds-id"</string>
@@ -704,7 +704,7 @@
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Tillader, at appen kan læse oplysninger om Wi-Fi-netværk, f.eks. hvorvidt Wi-Fi er aktiveret og navnet på forbundne Wi-Fi-enheder."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"oprette og afbryde Wi-Fi-forbindelse"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Tillader, at appen kan oprette og afbryde forbindelsen fra Wi-Fi-adgangspunkter og foretage ændringer i enhedskonfigurationen for Wi-Fi-netværk."</string>
- <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"tillad Wi-Fi-multicastmodtagelse"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"tillade Wi-Fi-multicastmodtagelse"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Tillader, at appen kan modtage pakker, der sendes til alle enheder på et Wi-Fi-netværk ved hjælp af multicastadresser, ikke kun din tablet. Den bruger mere strøm end tilstanden, der ikke anvender multicast."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Giver appen lov til at modtage pakker, der sendes til alle enheder og ikke bare dit tv på et Wi-Fi-netværk ved hjælp af multicast-adresser. Dette bruger mere strøm end tilstanden uden multicast."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Tillader, at appen kan modtage pakker, der sendes til alle enheder på et Wi-Fi-netværk ved hjælp af multicastadresser, ikke kun din telefon. Den bruger mere strøm end tilstanden, der ikke anvender multicast."</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ønsker at aktivere Udforsk ved berøring. Når Udforsk ved berøring er aktiveret, kan du høre eller se beskrivelser af, hvad der er under din finger, eller udføre bevægelser for at interagere med telefonen."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"for 1 måned siden"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Før for 1 måned siden"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"for 1 sekund siden"</item>
- <item quantity="other" msgid="3903706804349556379">"for <xliff:g id="COUNT">%d</xliff:g> sekunder siden"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"for 1 minut siden"</item>
- <item quantity="other" msgid="2176942008915455116">"for <xliff:g id="COUNT">%d</xliff:g> minutter siden"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"for 1 time siden"</item>
- <item quantity="other" msgid="2467273239587587569">"for <xliff:g id="COUNT">%d</xliff:g> timer siden"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Inden for de seneste <xliff:g id="COUNT_1">%d</xliff:g> dage</item>
+ <item quantity="other">Inden for de seneste <xliff:g id="COUNT_1">%d</xliff:g> dage</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Seneste måned"</string>
<string name="older" msgid="5211975022815554840">"Ældre"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"i går"</item>
- <item quantity="other" msgid="2479586466153314633">"for <xliff:g id="COUNT">%d</xliff:g> dage siden"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"om 1 sekund"</item>
- <item quantity="other" msgid="1241926116443974687">"om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"om 1 minut"</item>
- <item quantity="other" msgid="3330713936399448749">"om <xliff:g id="COUNT">%d</xliff:g> minutter"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"om 1 time"</item>
- <item quantity="other" msgid="547290677353727389">"om <xliff:g id="COUNT">%d</xliff:g> timer"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"i morgen"</item>
- <item quantity="other" msgid="5109449375100953247">"om <xliff:g id="COUNT">%d</xliff:g> dage"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"for 1 sek. siden"</item>
- <item quantity="other" msgid="3699169366650930415">"for <xliff:g id="COUNT">%d</xliff:g> sek. siden"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"for 1 min. siden"</item>
- <item quantity="other" msgid="851164968597150710">"for <xliff:g id="COUNT">%d</xliff:g> min. siden"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"for 1 time siden"</item>
- <item quantity="other" msgid="6889970745748538901">"for <xliff:g id="COUNT">%d</xliff:g> timer siden"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"i går"</item>
- <item quantity="other" msgid="3453342639616481191">"for <xliff:g id="COUNT">%d</xliff:g> dage siden"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"om 1 sek."</item>
- <item quantity="other" msgid="5495880108825805108">"om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"om 1 min."</item>
- <item quantity="other" msgid="4216113292706568726">"om <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"om 1 time"</item>
- <item quantity="other" msgid="3705373766798013406">"om <xliff:g id="COUNT">%d</xliff:g> timer"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"i morgen"</item>
- <item quantity="other" msgid="2973062968038355991">"om <xliff:g id="COUNT">%d</xliff:g> dage"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"den <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"i <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"uger"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"Ét sekund"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"Ét minut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"Én time"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minutter</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutter</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> timer</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> timer</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne video kan ikke streames på denne enhed."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videoen kan ikke afspilles."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Ukendt ringetone"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi-netværk tilgængeligt"</item>
- <item quantity="other" msgid="4192424489168397386">"Tilgængelige Wi-Fi-netværk"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Åbent Wi-Fi-netværk tilgængeligt"</item>
- <item quantity="other" msgid="7915895323644292768">"Der er åbne Wi-Fi-netværk tilgængelige"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Tilgængelige Wi-Fi-netværk</item>
+ <item quantity="other">Tilgængelige Wi-Fi-netværk</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Åbne Wi-Fi-netværk er tilgængelige</item>
+ <item quantity="other">Åbne Wi-Fi-netværk er tilgængelige</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Log ind på Wi-Fi-netværket"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Log ind på netværk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilsluttet som en medieenhed"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilsluttet som et kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Forbundet til en MIDI-enhed"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilsluttet som et installationsprogram"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Tilsluttet et USB-ekstraudstyr"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Tryk for at se andre valgmuligheder for USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Spring over"</string>
<string name="no_matches" msgid="8129421908915840737">"Der er ingen matches"</string>
<string name="find_on_page" msgid="1946799233822820384">"Find på siden"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 match"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Udfør"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Demonterer USB-lageret..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Demonterer SD-kortet..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Opret en pinkode til ændring af begrænsninger"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Pinkoderne stemmer ikke overens. Prøv igen."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Pinkoden er for kort. Den skal være på mindst 4 tal."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Prøv igen om 1 sekund"</item>
- <item quantity="other" msgid="4730868920742952817">"Prøv igen om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Prøv igen om <xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="other">Prøv igen om <xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Prøv igen senere"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Stryg ned fra toppen for at afslutte fuld skærm"</string>
<string name="done_label" msgid="2093726099505892398">"Udfør"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Batterisparefunktionen hjælper med at forlænge batteriets levetid ved at reducere enhedens ydeevne og begrænse vibration, placeringstjenester og det meste baggrundsdata. E-mail, beskedfunktioner og andre apps, der benytter synkronisering, opdateres muligvis ikke, medmindre du åbner dem.\n\nBatterisparefunktionen slukker automatisk, når enheden oplader."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Indtil din nedetid slutter kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Indtil nedetiden ophører"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"I ét minut (indtil <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"I %1$d minutter (indtil <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"I én time (indtil <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"I %1$d timer (indtil <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"I ét minut"</item>
- <item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"I én time"</item>
- <item quantity="other" msgid="5408537517529822157">"I %d timer"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">I %1$d minutter (indtil <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">I %1$d minutter (indtil <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">I %1$d timer (indtil <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">I %1$d timer (indtil <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">I %d minutter</item>
+ <item quantity="other">I %d minutter</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">I %d timer</item>
+ <item quantity="other">I %d timer</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Uendeligt"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Skjul"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5605ccc..c246c242 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Ihre SIM-Karte ist mit einem PUK gesperrt. Geben Sie zum Entsperren den PUK-Code ein."</string>
<string name="needPuk2" msgid="4526033371987193070">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
<string name="enablePin" msgid="209412020907207950">"Fehler. SIM-/RUIM-Sperre aktivieren."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuch, bevor Ihre SIM-Karte gesperrt wird."</item>
- <item quantity="other" msgid="7530597808358774740">"Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuche, bevor Ihre SIM-Karte gesperrt wird."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Sie haben noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche, bevor Ihre SIM-Karte gesperrt wird.</item>
+ <item quantity="one">Sie haben noch <xliff:g id="NUMBER_0">%d</xliff:g> Versuch, bevor Ihre SIM-Karte gesperrt wird.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Anrufer-ID für eingehenden Anruf"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> fordert die Aktivierung von \"Tippen & Entdecken\". Wenn \"Tippen & Entdecken\" aktiviert ist, können Sie Beschreibungen dessen hören oder sehen, was sich unter ihren Fingern befindet, oder Gesten ausführen, um mit dem Telefon zu kommunizieren."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Vor 1 Monat"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"vor 1 Sekunde"</item>
- <item quantity="other" msgid="3903706804349556379">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"vor 1 Minute"</item>
- <item quantity="other" msgid="2176942008915455116">"vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"vor 1 Stunde"</item>
- <item quantity="other" msgid="2467273239587587569">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Letzte <xliff:g id="COUNT_1">%d</xliff:g> Tage</item>
+ <item quantity="one">Gestern (<xliff:g id="COUNT_0">%d</xliff:g> Tag)</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Letzter Monat"</string>
<string name="older" msgid="5211975022815554840">"Älter"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"gestern"</item>
- <item quantity="other" msgid="2479586466153314633">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"in 1 Sekunde"</item>
- <item quantity="other" msgid="1241926116443974687">"in <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"in 1 Minute"</item>
- <item quantity="other" msgid="3330713936399448749">"in <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"in 1 Stunde"</item>
- <item quantity="other" msgid="547290677353727389">"In <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"morgen"</item>
- <item quantity="other" msgid="5109449375100953247">"in <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"vor 1 Sekunde"</item>
- <item quantity="other" msgid="3699169366650930415">"vor <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"vor 1 Minute"</item>
- <item quantity="other" msgid="851164968597150710">"vor <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"vor 1 Stunde"</item>
- <item quantity="other" msgid="6889970745748538901">"vor <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"gestern"</item>
- <item quantity="other" msgid="3453342639616481191">"vor <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"in 1 Sekunde"</item>
- <item quantity="other" msgid="5495880108825805108">"in <xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"in 1 Minute"</item>
- <item quantity="other" msgid="4216113292706568726">"in <xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"in 1 Stunde"</item>
- <item quantity="other" msgid="3705373766798013406">"In <xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"morgen"</item>
- <item quantity="other" msgid="2973062968038355991">"in <xliff:g id="COUNT">%d</xliff:g> Tagen"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"am <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"um <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"im Jahr <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"Wochen"</string>
<string name="year" msgid="4001118221013892076">"Jahr"</string>
<string name="years" msgid="6881577717993213522">"Jahre"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 Sekunde"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> Sekunden"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 Minute"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> Minuten"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 Stunde"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> Stunden"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Sekunden</item>
+ <item quantity="one">1 Sekunde</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Minuten</item>
+ <item quantity="one">1 Minute</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> Stunden</item>
+ <item quantity="one">1 Stunde</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobleme"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Dieses Video ist nicht für Streaming auf diesem Gerät gültig."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Video kann nicht wiedergegeben werden."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Keine"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Klingeltöne"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Unbekannter Klingelton"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"WLAN-Netzwerk verfügbar"</item>
- <item quantity="other" msgid="4192424489168397386">"WLAN-Netzwerke verfügbar"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Verfügbares WLAN-Netzwerk öffnen"</item>
- <item quantity="other" msgid="7915895323644292768">"Verfügbare WLAN-Netzwerke öffnen"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">WLAN-Netzwerke verfügbar</item>
+ <item quantity="one">WLAN-Netzwerk verfügbar</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Verfügbare WLAN-Netzwerke öffnen</item>
+ <item quantity="one">Verfügbares WLAN-Netzwerk öffnen</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Im WLAN-Netzwerk anmelden"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Im Netzwerk anmelden"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Als Mediengerät angeschlossen"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Als Kamera angeschlossen"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Als MIDI-Gerät verbunden"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Als Installationsprogramm angeschlossen"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Mit USB-Zubehör verbunden"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Für mehr USB-Optionen berühren"</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Überspringen"</string>
<string name="no_matches" msgid="8129421908915840737">"Keine Treffer"</string>
<string name="find_on_page" msgid="1946799233822820384">"Auf Seite suchen"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 Treffer"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> von <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> von <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 Treffer</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Fertig"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB-Speicher wird getrennt..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD-Karte wird getrennt..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"PIN für das Ändern von Einschränkungen erstellen"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Die PINs stimmen nicht überein. Bitte versuchen Sie es erneut."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Die PIN ist zu kurz. Sie muss mindestens 4 Ziffern umfassen."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"In 1 Sek. wiederholen"</item>
- <item quantity="other" msgid="4730868920742952817">"In <xliff:g id="COUNT">%d</xliff:g> Sek. wiederholen"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">In <xliff:g id="COUNT">%d</xliff:g> Sek. wiederholen</item>
+ <item quantity="one">In 1 Sek. wiederholen</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Später erneut versuchen"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Zum Schließen des Vollbilds von oben nach unten wischen"</string>
<string name="done_label" msgid="2093726099505892398">"Fertig"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Der Energiesparmodus schont den Akku, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion sowie die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail, SMS/MMS und andere Apps, die auf Ihrem Gerät synchronisiert werden, werden möglicherweise erst nach dem Öffnen aktualisiert.\n\nDer Energiesparmodus wird automatisch deaktiviert, wenn Ihr Gerät aufgeladen wird."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Bis zum Ende der Downtime um <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Bis zum Ende der Inaktivität"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1 Minute (bis <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d Minuten (bis <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1 Stunde (bis <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d Stunden (bis <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Für eine Minute"</item>
- <item quantity="other" msgid="6924190729213550991">"Für %d Minuten"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Für eine Stunde"</item>
- <item quantity="other" msgid="5408537517529822157">"Für %d Stunden"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d Minuten (bis <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 Minute (bis <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d Stunden (bis <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 Stunde (bis <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Für %d Minuten</item>
+ <item quantity="one">Für 1 Minute</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Für %d Stunden</item>
+ <item quantity="one">Für eine Stunde</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Unbegrenzt"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Minimieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9229bc6..7e12895 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Η κάρτα SIM έχει κλειδωθεί με κωδικό PUK. Πληκτρολογήστε τον κωδικό PUK για να την ξεκλειδώσετε."</string>
<string name="needPuk2" msgid="4526033371987193070">"Πληκτρολογήστε τον κωδικό PUK2 για την κατάργηση αποκλεισμού της κάρτας SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Ανεπιτυχής προσπάθεια. Ενεργοποιήστε το Κλείδωμα SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Απομένει άλλη <xliff:g id="NUMBER">%d</xliff:g> προσπάθεια προτού η κάρτα SIM κλειδωθεί."</item>
- <item quantity="other" msgid="7530597808358774740">"Απομένουν <xliff:g id="NUMBER">%d</xliff:g> προσπάθειες προτού η κάρτα SIM κλειδωθεί."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Απομένουν άλλες <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες προτού κλειδωθεί η κάρτα SIM.</item>
+ <item quantity="one">Απομένει άλλη <xliff:g id="NUMBER_0">%d</xliff:g> προσπάθεια προτού κλειδωθεί η κάρτα SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Εισερχόμενη αναγνώριση κλήσης"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"πριν από 1 δευτερόλεπτο"</item>
- <item quantity="other" msgid="3903706804349556379">"πριν από <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"πριν από 1 λεπτό"</item>
- <item quantity="other" msgid="2176942008915455116">"πριν από <xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"πριν από 1 ώρα"</item>
- <item quantity="other" msgid="2467273239587587569">"πριν από <xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Τελευταίες <xliff:g id="COUNT_1">%d</xliff:g> ημέρες</item>
+ <item quantity="one">Τελευταία <xliff:g id="COUNT_0">%d</xliff:g> ημέρα</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Τελευταίος μήνας"</string>
<string name="older" msgid="5211975022815554840">"Παλαιότερα"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"χθες"</item>
- <item quantity="other" msgid="2479586466153314633">"πριν από <xliff:g id="COUNT">%d</xliff:g> ημέρες"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"σε 1 δευτερόλεπτο"</item>
- <item quantity="other" msgid="1241926116443974687">"σε <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"σε 1 λεπτό"</item>
- <item quantity="other" msgid="3330713936399448749">"σε <xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"σε 1 ώρα"</item>
- <item quantity="other" msgid="547290677353727389">"σε <xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"αύριο"</item>
- <item quantity="other" msgid="5109449375100953247">"σε <xliff:g id="COUNT">%d</xliff:g> ημέρες"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"πριν από 1 δευτερόλεπτο"</item>
- <item quantity="other" msgid="3699169366650930415">"πριν από <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"πριν από 1 λεπτό"</item>
- <item quantity="other" msgid="851164968597150710">"πριν από <xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"πριν από 1 ώρα"</item>
- <item quantity="other" msgid="6889970745748538901">"πριν από <xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"χθες"</item>
- <item quantity="other" msgid="3453342639616481191">"πριν από <xliff:g id="COUNT">%d</xliff:g> ημέρες"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"σε 1 δευτερόλεπτο"</item>
- <item quantity="other" msgid="5495880108825805108">"σε <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"σε 1 λεπτό"</item>
- <item quantity="other" msgid="4216113292706568726">"σε <xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"σε 1 ώρα"</item>
- <item quantity="other" msgid="3705373766798013406">"σε <xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"αύριο"</item>
- <item quantity="other" msgid="2973062968038355991">"σε <xliff:g id="COUNT">%d</xliff:g> ημέρες"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"στις <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"στις <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"το <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"εβδομάδες"</string>
<string name="year" msgid="4001118221013892076">"έτος"</string>
<string name="years" msgid="6881577717993213522">"έτη"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 δευτερόλεπτο"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 λεπτό"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> λεπτά"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ώρα"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ώρες"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα</item>
+ <item quantity="one">1 δευτερόλεπτο</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> λεπτά</item>
+ <item quantity="one">1 λεπτό</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ώρες</item>
+ <item quantity="one">1 ώρα</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Κανένας"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ήχοι κλήσης"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Άγνωστος ήχος κλήσης"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Υπάρχει διαθέσιμο δίκτυο Wi-Fi"</item>
- <item quantity="other" msgid="4192424489168397386">"Υπάρχουν διαθέσιμα δίκτυα Wi-Fi"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Υπάρχουν διαθέσιμα δίκτυα Wi-Fi</item>
+ <item quantity="one">Υπάρχει διαθέσιμο δίκτυο Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi</item>
+ <item quantity="one">Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Σύνδεση στο δίκτυο Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Σύνδεση σε δίκτυο"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Συνδεδεμένο ως συσκευή πολυμέσων"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Συνδεδεμένο ως φωτογραφική μηχανή"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Συνδεθήκατε ως συσκευή MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Συνδεδεμένο ως πρόγραμμα εγκατάστασης"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Σύνδεση σε αξεσουάρ USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Αγγίξτε για άλλες επιλογές USB."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 αποτέλεσμα"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> από <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> από <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 αντιστοιχία</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Τέλος"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Αποσύνδεση του χώρου αποθήκευσης USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Αφαίρεση κάρτας SD..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"Το PIN είναι υπερβολικά μικρό. Πρέπει να έχει μέγεθος τουλάχιστον 4 χαρακτήρων."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Επανάληψη σε 1 δευτ."</item>
- <item quantity="other" msgid="4730868920742952817">"Επανάληψη σε <xliff:g id="COUNT">%d</xliff:g> δευτ."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Δοκιμάστε ξανά σε <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα</item>
+ <item quantity="one">Δοκιμάστε ξανά σε 1 δευτερόλεπτο</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Δοκιμάστε ξανά αργότερα"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Σάρωση προς τα κάτω για έξοδο από πλήρη οθόνη"</string>
<string name="done_label" msgid="2093726099505892398">"Τέλος"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Προκειμένου να βελτιώσει τη διάρκεια ζωής της μπαταρίας σας, η Εξοικονόμηση μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει λειτουργίες όπως η δόνηση, οι υπηρεσίες τοποθεσίας και τα περισσότερα δεδομένα παρασκηνίου. Το ηλεκτρονικό ταχυδρομείο, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται έως ότου τις ανοίξετε.\n\nΗ Εξοικονόμηση μπαταρίας απενεργοποιείται αυτόματα όταν η συσκευή σας φορτίζει."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Έως τη λήξη του νεκρού χρόνου σας στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Έως τη λήξη του νεκρού χρόνου σας"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Για ένα λεπτό (έως τις <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Για %1$d λεπτά (έως τις <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Για μία ώρα (έως τις <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Για %1$d ώρες (έως τις <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item>
- <item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Για μία ώρα"</item>
- <item quantity="other" msgid="5408537517529822157">"Για %d ώρες"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Για %1$d λεπτά (έως τις <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Για ένα λεπτό (έως τις <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Για %1$d ώρες (έως τις <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Για μία ώρα (έως τις <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Για %d λεπτά</item>
+ <item quantity="one">Για ένα λεπτό</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Για %d ώρες</item>
+ <item quantity="one">Για μία ώρα</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Έως τις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Επ\' αόριστον"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Σύμπτυξη"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f7f62e9..dcbc375 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Your SIM card is PUK-locked. Type the PUK code to unlock it."</string>
<string name="needPuk2" msgid="4526033371987193070">"Type PUK2 to unblock SIM card."</string>
<string name="enablePin" msgid="209412020907207950">"Unsuccessful, enable SIM/RUIM Lock."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"You have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM is locked."</item>
- <item quantity="other" msgid="7530597808358774740">"You have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM is locked."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
+ <item quantity="one">You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before SIM is locked.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Incoming Caller ID"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wants to enable Explore by Touch. When Explore by Touch is turned on, you can hear or see descriptions of what\'s under your finger or perform gestures to interact with the phone."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 month ago"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Before 1 month ago"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 second ago"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> seconds ago"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minute ago"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minutes ago"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 hour ago"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
+ <item quantity="one">Last <xliff:g id="COUNT_0">%d</xliff:g> day</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Last month"</string>
<string name="older" msgid="5211975022815554840">"Older"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"yesterday"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> days ago"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"in 1 second"</item>
- <item quantity="other" msgid="1241926116443974687">"in <xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"in 1 minute"</item>
- <item quantity="other" msgid="3330713936399448749">"in <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"in 1 hour"</item>
- <item quantity="other" msgid="547290677353727389">"in <xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"tomorrow"</item>
- <item quantity="other" msgid="5109449375100953247">"in <xliff:g id="COUNT">%d</xliff:g> days"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 sec ago"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> secs ago"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min ago"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> mins ago"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 hour ago"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"yesterday"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> days ago"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"in 1 sec"</item>
- <item quantity="other" msgid="5495880108825805108">"in <xliff:g id="COUNT">%d</xliff:g> secs"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"in 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"in <xliff:g id="COUNT">%d</xliff:g> mins"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"in 1 hour"</item>
- <item quantity="other" msgid="3705373766798013406">"in <xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"tomorrow"</item>
- <item quantity="other" msgid="2973062968038355991">"in <xliff:g id="COUNT">%d</xliff:g> days"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"on <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"in<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"weeks"</string>
<string name="year" msgid="4001118221013892076">"year"</string>
<string name="years" msgid="6881577717993213522">"years"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 second"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hour"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> seconds</item>
+ <item quantity="one">1 second</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutes</item>
+ <item quantity="one">1 minute</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hours</item>
+ <item quantity="one">1 hour</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video problem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"This video isn\'t valid for streaming to this device."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Can\'t play this video."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"None"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi network available"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi networks available"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Open available Wi-Fi network"</item>
- <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi networks available</item>
+ <item quantity="one">Wi-Fi network available</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Open Wi-Fi networks available</item>
+ <item quantity="one">Open Wi-Fi network available</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Sign in to Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connected as a media device"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connected as a camera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connected as a MIDI device"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connected as an installer"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connected to a USB accessory"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Touch for other USB options."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Skip"</string>
<string name="no_matches" msgid="8129421908915840737">"No matches"</string>
<string name="find_on_page" msgid="1946799233822820384">"Find on page"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 Match"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 match</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Done"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Unmounting USB storage…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Unmounting SD card…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINs don\'t match. Try again."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN is too short. Must be at least 4 digits."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Try again in 1 second"</item>
- <item quantity="other" msgid="4730868920742952817">"Try again in <xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
+ <item quantity="one">Try again in 1 second</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Try again later"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Swipe down from the top to exit full screen."</string>
<string name="done_label" msgid="2093726099505892398">"Done"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Until your downtime ends"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"For one minute (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"For %1$d minutes (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"For one hour (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"For %1$d hours (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"For one minute"</item>
- <item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"For one hour"</item>
- <item quantity="other" msgid="5408537517529822157">"For %d hours"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">For one minute (until <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">For one hour (until <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">For %d minutes</item>
+ <item quantity="one">For one minute</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">For %d hours</item>
+ <item quantity="one">For one hour</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Collapse"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index f7f62e9..dcbc375 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Your SIM card is PUK-locked. Type the PUK code to unlock it."</string>
<string name="needPuk2" msgid="4526033371987193070">"Type PUK2 to unblock SIM card."</string>
<string name="enablePin" msgid="209412020907207950">"Unsuccessful, enable SIM/RUIM Lock."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"You have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM is locked."</item>
- <item quantity="other" msgid="7530597808358774740">"You have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM is locked."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
+ <item quantity="one">You have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before SIM is locked.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Incoming Caller ID"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wants to enable Explore by Touch. When Explore by Touch is turned on, you can hear or see descriptions of what\'s under your finger or perform gestures to interact with the phone."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 month ago"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Before 1 month ago"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 second ago"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> seconds ago"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minute ago"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minutes ago"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 hour ago"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
+ <item quantity="one">Last <xliff:g id="COUNT_0">%d</xliff:g> day</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Last month"</string>
<string name="older" msgid="5211975022815554840">"Older"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"yesterday"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> days ago"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"in 1 second"</item>
- <item quantity="other" msgid="1241926116443974687">"in <xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"in 1 minute"</item>
- <item quantity="other" msgid="3330713936399448749">"in <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"in 1 hour"</item>
- <item quantity="other" msgid="547290677353727389">"in <xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"tomorrow"</item>
- <item quantity="other" msgid="5109449375100953247">"in <xliff:g id="COUNT">%d</xliff:g> days"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 sec ago"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> secs ago"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min ago"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> mins ago"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 hour ago"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> hours ago"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"yesterday"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> days ago"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"in 1 sec"</item>
- <item quantity="other" msgid="5495880108825805108">"in <xliff:g id="COUNT">%d</xliff:g> secs"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"in 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"in <xliff:g id="COUNT">%d</xliff:g> mins"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"in 1 hour"</item>
- <item quantity="other" msgid="3705373766798013406">"in <xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"tomorrow"</item>
- <item quantity="other" msgid="2973062968038355991">"in <xliff:g id="COUNT">%d</xliff:g> days"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"on <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"at <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"in<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"weeks"</string>
<string name="year" msgid="4001118221013892076">"year"</string>
<string name="years" msgid="6881577717993213522">"years"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 second"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hour"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hours"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> seconds</item>
+ <item quantity="one">1 second</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutes</item>
+ <item quantity="one">1 minute</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hours</item>
+ <item quantity="one">1 hour</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video problem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"This video isn\'t valid for streaming to this device."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Can\'t play this video."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"None"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi network available"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi networks available"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Open available Wi-Fi network"</item>
- <item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi networks available</item>
+ <item quantity="one">Wi-Fi network available</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Open Wi-Fi networks available</item>
+ <item quantity="one">Open Wi-Fi network available</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Sign in to Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connected as a media device"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connected as a camera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connected as a MIDI device"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connected as an installer"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connected to a USB accessory"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Touch for other USB options."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Skip"</string>
<string name="no_matches" msgid="8129421908915840737">"No matches"</string>
<string name="find_on_page" msgid="1946799233822820384">"Find on page"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 Match"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 match</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Done"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Unmounting USB storage…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Unmounting SD card…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Create a PIN for modifying restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINs don\'t match. Try again."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN is too short. Must be at least 4 digits."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Try again in 1 second"</item>
- <item quantity="other" msgid="4730868920742952817">"Try again in <xliff:g id="COUNT">%d</xliff:g> seconds"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
+ <item quantity="one">Try again in 1 second</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Try again later"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Swipe down from the top to exit full screen."</string>
<string name="done_label" msgid="2093726099505892398">"Done"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Until your downtime ends"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"For one minute (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"For %1$d minutes (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"For one hour (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"For %1$d hours (until <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"For one minute"</item>
- <item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"For one hour"</item>
- <item quantity="other" msgid="5408537517529822157">"For %d hours"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">For one minute (until <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">For one hour (until <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">For %d minutes</item>
+ <item quantity="one">For one minute</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">For %d hours</item>
+ <item quantity="one">For one hour</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Collapse"</string>
diff --git a/core/res/res/values-en-rSG/strings.xml b/core/res/res/values-en-rSG/strings.xml
index 09a8490..5ba1082b 100644
--- a/core/res/res/values-en-rSG/strings.xml
+++ b/core/res/res/values-en-rSG/strings.xml
@@ -776,22 +776,6 @@
<skip />
<!-- no translation found for beforeOneMonthDurationPast (7578100953282866827) -->
<skip />
- <!-- no translation found for num_seconds_ago:one (7416512229671810725) -->
- <!-- no translation found for num_seconds_ago:other (8138756910300398447) -->
- <!-- no translation found for num_minutes_ago:one (8620869479299420562) -->
- <!-- no translation found for num_minutes_ago:other (5065488162050522741) -->
- <!-- no translation found for num_hours_ago:one (853404611989669641) -->
- <!-- no translation found for num_hours_ago:other (3558873784561756849) -->
- <!-- no translation found for num_days_ago:one (4222479980812128212) -->
- <!-- no translation found for num_days_ago:other (5445701370433601703) -->
- <!-- no translation found for in_num_seconds:one (4253290037777327003) -->
- <!-- no translation found for in_num_seconds:other (1280033870920841404) -->
- <!-- no translation found for in_num_minutes:one (1487585791027953091) -->
- <!-- no translation found for in_num_minutes:other (6274204576475209932) -->
- <!-- no translation found for in_num_hours:one (6501470863235186391) -->
- <!-- no translation found for in_num_hours:other (4415358752953289251) -->
- <!-- no translation found for in_num_days:one (5608475533104443893) -->
- <!-- no translation found for in_num_days:other (3827193006163842267) -->
<!-- no translation found for preposition_for_date (2689847983632851560) -->
<skip />
<!-- no translation found for preposition_for_time (2613388053493148013) -->
diff --git a/core/res/res/values-en-rUS/strings.xml b/core/res/res/values-en-rUS/strings.xml
index fdc0d69..adae7f4 100644
--- a/core/res/res/values-en-rUS/strings.xml
+++ b/core/res/res/values-en-rUS/strings.xml
@@ -777,22 +777,6 @@
<skip />
<!-- no translation found for beforeOneMonthDurationPast (7578100953282866827) -->
<skip />
- <!-- no translation found for num_seconds_ago:one (7416512229671810725) -->
- <!-- no translation found for num_seconds_ago:other (8138756910300398447) -->
- <!-- no translation found for num_minutes_ago:one (8620869479299420562) -->
- <!-- no translation found for num_minutes_ago:other (5065488162050522741) -->
- <!-- no translation found for num_hours_ago:one (853404611989669641) -->
- <!-- no translation found for num_hours_ago:other (3558873784561756849) -->
- <!-- no translation found for num_days_ago:one (4222479980812128212) -->
- <!-- no translation found for num_days_ago:other (5445701370433601703) -->
- <!-- no translation found for in_num_seconds:one (4253290037777327003) -->
- <!-- no translation found for in_num_seconds:other (1280033870920841404) -->
- <!-- no translation found for in_num_minutes:one (1487585791027953091) -->
- <!-- no translation found for in_num_minutes:other (6274204576475209932) -->
- <!-- no translation found for in_num_hours:one (6501470863235186391) -->
- <!-- no translation found for in_num_hours:other (4415358752953289251) -->
- <!-- no translation found for in_num_days:one (5608475533104443893) -->
- <!-- no translation found for in_num_days:other (3827193006163842267) -->
<!-- no translation found for preposition_for_date (2689847983632851560) -->
<skip />
<!-- no translation found for preposition_for_time (2613388053493148013) -->
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 19c731f..e916cb6 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Tu tarjeta SIM está bloqueada con PUK. Escribe el código PUK para desbloquearla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Escribir PUK2 para desbloquear la tarjeta SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Error; habilita el bloqueo de SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Te queda <xliff:g id="NUMBER">%d</xliff:g> intento antes de que se bloquee la tarjeta SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"Te quedan <xliff:g id="NUMBER">%d</xliff:g> intentos antes de que se bloquee la tarjeta SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Tienes <xliff:g id="NUMBER_1">%d</xliff:g> intentos más antes de que se bloquee la tarjeta SIM.</item>
+ <item quantity="one">Tienes <xliff:g id="NUMBER_0">%d</xliff:g> un intento más antes de que se bloquee la tarjeta SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identificador de llamadas entrantes"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> desea activar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el dispositivo."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Hace 1 mes."</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Anterior a 1 mes atrás"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"hace 1 segundo"</item>
- <item quantity="other" msgid="3903706804349556379">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Hace 1 minuto."</item>
- <item quantity="other" msgid="2176942008915455116">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Hace 1 hora"</item>
- <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Quedan <xliff:g id="COUNT_1">%d</xliff:g> días.</item>
+ <item quantity="one">Queda <xliff:g id="COUNT_0">%d</xliff:g> día.</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Último mes"</string>
<string name="older" msgid="5211975022815554840">"Antiguos"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ayer"</item>
- <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"en 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"en <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"en 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"en <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"en 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"en <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"mañana"</item>
- <item quantity="other" msgid="5109449375100953247">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"hace 1 segundo"</item>
- <item quantity="other" msgid="3699169366650930415">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"hace 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"Hace <xliff:g id="COUNT">%d</xliff:g> minutos."</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Hace 1 hora"</item>
- <item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ayer"</item>
- <item quantity="other" msgid="3453342639616481191">"Hace <xliff:g id="COUNT">%d</xliff:g> días."</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"en 1 segundo"</item>
- <item quantity="other" msgid="5495880108825805108">"en <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"en 1 minuto"</item>
- <item quantity="other" msgid="4216113292706568726">"en <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"en 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"en <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"mañana"</item>
- <item quantity="other" msgid="2973062968038355991">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"activado <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"a las <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"en <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"año"</string>
<string name="years" msgid="6881577717993213522">"años"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">1 segundo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ <item quantity="one">1 minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ <item quantity="one">1 hora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemas de video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"No es posible transmitir este video al dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No se puede reproducir el video."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos de llamada"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tono de llamada desconocido"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Red disponible de Wi-Fi"</item>
- <item quantity="other" msgid="4192424489168397386">"redes disponibles de Wi-Fi"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Abrir red disponible de Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"Abrir redes disponibles de Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">redes de Wi-Fi disponibles</item>
+ <item quantity="one">red de Wi-Fi disponible</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Abrir redes de Wi-Fi disponibles</item>
+ <item quantity="one">Abrir red de Wi-Fi disponible</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Accede a una red Wi-Fi."</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Acceder a la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectado como dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como un instalador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectado a un accesorio USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toca para acceder a otras opciones de USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Omitir"</string>
<string name="no_matches" msgid="8129421908915840737">"Sin coincidencias"</string>
<string name="find_on_page" msgid="1946799233822820384">"Buscar en la página"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 coincidencia"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 coincidencia</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Listo"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Desactivando almacenamiento USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Desactivando tarjeta SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crear PIN para modificar restricciones"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Los PIN no coinciden. Vuelve a intentarlo."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"El PIN es demasiado corto. Debe tener al menos 4 dígitos."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Intentar en 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Intentar en <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Vuelve a intentarlo en <xliff:g id="COUNT">%d</xliff:g> segundos.</item>
+ <item quantity="one">Vuelve a intentarlo en 1 segundo.</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Vuelve a intentar más tarde."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Desliza el dedo hacia abajo para salir de la pantalla completa."</string>
<string name="done_label" msgid="2093726099505892398">"Listo"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Para ayudar a mejorar la duración de la batería, el ahorro de batería reduce el rendimiento del dispositivo y limita la vibración, los servicios de ubicación y la mayoría de los datos en segundo plano. Es posible que el correo electrónico, la mensajería y otras aplicaciones que se basan en la sincronización no puedan actualizarse, a menos que los abras.\n\nEl ahorro de batería se desactiva de forma automática cuando el dispositivo se está cargando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que termine el tiempo de inactividad a la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Hasta que finalice el tiempo de inactividad"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Durante 1 minuto; hasta la(s) <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>"</item>
- <item quantity="other" msgid="2787867221129368935">"Durante %1$d minutos; hasta la(s) <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Durante 1 hora; hasta la(s) <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>"</item>
- <item quantity="other" msgid="2827214920627669898">"Durante %1$d horas; hasta la(s) <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Durante una hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Durante %1$d minutos hasta la(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g></item>
+ <item quantity="one">Durante 1 minuto; hasta la(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g></item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Durante %1$d horas, hasta la(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g></item>
+ <item quantity="one">Durante 1 hora; hasta la(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g></item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Durante %d minutos</item>
+ <item quantity="one">Durante un minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Durante %d horas</item>
+ <item quantity="one">Durante 1 hora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Contraer"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f06832d..60a543f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"La tarjeta SIM está bloqueada con el código PUK. Introduce el código PUK para desbloquearla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduce el código PUK2 para desbloquear la tarjeta SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Error, habilitar bloqueo de SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Te queda <xliff:g id="NUMBER">%d</xliff:g> intento para bloquear la tarjeta SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"Quedan <xliff:g id="NUMBER">%d</xliff:g> intentos para bloquear la tarjeta SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos para bloquear la tarjeta SIM.</item>
+ <item quantity="one">Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento para bloquear la tarjeta SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID de emisor de llamada entrante"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quiere habilitar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el teléfono."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Hace un mes"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Hace más de un mes"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Hace 1 segundo"</item>
- <item quantity="other" msgid="3903706804349556379">"Hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Hace 1 minuto"</item>
- <item quantity="other" msgid="2176942008915455116">"Hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Hace 1 hora"</item>
- <item quantity="other" msgid="2467273239587587569">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> <xliff:g id="COUNT_1">%d</xliff:g> últimos días</item>
+ <item quantity="one">Último día (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"El mes pasado"</string>
<string name="older" msgid="5211975022815554840">"Anterior"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"Ayer"</item>
- <item quantity="other" msgid="2479586466153314633">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"dentro de 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"dentro de <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"dentro de 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"dentro de <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"dentro de 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"dentro de <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"mañana"</item>
- <item quantity="other" msgid="5109449375100953247">"dentro de <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"hace 1 segundo"</item>
- <item quantity="other" msgid="3699169366650930415">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"hace 1 minuto"</item>
- <item quantity="other" msgid="851164968597150710">"hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"hace 1 hora"</item>
- <item quantity="other" msgid="6889970745748538901">"hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"Ayer"</item>
- <item quantity="other" msgid="3453342639616481191">"hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"dentro de 1 segundo"</item>
- <item quantity="other" msgid="5495880108825805108">"dentro de <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"dentro de 1 minuto"</item>
- <item quantity="other" msgid="4216113292706568726">"dentro de <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"dentro de 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"dentro de <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"mañana"</item>
- <item quantity="other" msgid="2973062968038355991">"dentro de <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"el <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"a las <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"en <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"año"</string>
<string name="years" msgid="6881577717993213522">"años"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">1 segundo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ <item quantity="one">1 minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ <item quantity="one">1 hora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Incidencias con el vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo no se puede transmitir al dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"No se puede reproducir el vídeo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tono desconocido"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Red Wi-Fi disponible"</item>
- <item quantity="other" msgid="4192424489168397386">"Redes Wi-Fi disponibles"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Red Wi-Fi abierta disponible"</item>
- <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abiertas disponibles"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Redes Wi-Fi disponibles</item>
+ <item quantity="one">Red Wi-Fi disponible</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Redes Wi-Fi abiertas disponibles</item>
+ <item quantity="one">Red Wi-Fi abierta disponible</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Iniciar sesión en red Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Iniciar sesión en la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como dispositivo multimedia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectado como dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como instalador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectado a un accesorio USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toca para acceder a otras opciones de USB"</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Saltar"</string>
<string name="no_matches" msgid="8129421908915840737">"No hay coincidencias."</string>
<string name="find_on_page" msgid="1946799233822820384">"Buscar en la página"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"Una coincidencia"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 coincidencia</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Listo"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Desactivando almacenamiento USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Desactivando tarjeta SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crear PIN para modificar restricciones"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Los números PIN no coinciden. Inténtalo de nuevo."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"El PIN es demasiado corto. Debe tener al menos 4 dígitos."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Inténtalo en 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Inténtalo en <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Vuelve a intentarlo en <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">Vuelve a intentarlo en 1 segundo</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Volver a intentar más tarde"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Desliza el dedo hacia abajo para salir de la pantalla completa"</string>
<string name="done_label" msgid="2093726099505892398">"Listo"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Para ayudar a mejorar la duración de la batería, la función de ahorro de energía reduce el rendimiento del dispositivo y limita la vibración, los servicios de ubicación y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo y mensajes, no se actualicen a menos que las abras.\n\nLa función de ahorro de energía se desactiva automáticamente cuando el dispositivo se está cargando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que el tiempo de inactividad finalice el <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Hasta que finalice el tiempo de inactividad"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Durante un minuto (hasta las <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Durante %1$d minutos (hasta las <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Durante una hora (hasta las <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Durante %1$d horas (hasta las <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Durante 1 hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Durante %1$d minutos (hasta las <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante un minuto (hasta las <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Durante %1$d horas (hasta las <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante una hora (hasta las <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Durante %d minutos</item>
+ <item quantity="one">Durante un minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Durante %d horas</item>
+ <item quantity="one">Durante una hora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Contraer"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 5a8e0a0..fe077c8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM-kaart on PUK-lukustatud. Avamiseks sisestage PUK-kood."</string>
<string name="needPuk2" msgid="4526033371987193070">"Sisestage SIM-kaardi blokeeringu tühistamiseks PUK2-kood."</string>
<string name="enablePin" msgid="209412020907207950">"Ebaõnnestus, SIM-i/RUIM-i lukustuse lubamine."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Teil on enne SIM-i lukustumist jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katse."</item>
- <item quantity="other" msgid="7530597808358774740">"Teil on enne SIM-i lukustumist jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katset."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Teil on enne SIM-kaardi lukustumist jäänud veel <xliff:g id="NUMBER_1">%d</xliff:g> katset.</item>
+ <item quantity="one">Teil on enne SIM-kaardi lukustumist jäänud veel <xliff:g id="NUMBER_0">%d</xliff:g> katse.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Sissetuleva kõne helistaja ID"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> soovib lubada puudutusega uurimise. Kui puudutusega uurimine on sisse lülitatud, kuulete või näete kirjeldusi asjade kohta, mis on teie sõrme all, või saate suhelda telefoniga liigutuste abil."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 kuu tagasi"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Varem kui 1 kuu tagasi"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 sekund tagasi"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sekundit tagasi"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minut tagasi"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minutit tagasi"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 tund tagasi"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> tundi tagasi"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Viimased <xliff:g id="COUNT_1">%d</xliff:g> päeva</item>
+ <item quantity="one">Viimane <xliff:g id="COUNT_0">%d</xliff:g> päev</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Eelmisel kuul"</string>
<string name="older" msgid="5211975022815554840">"Vanem"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"eile"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> päeva tagasi"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 sekundi pärast"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> sekundi pärast"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 minuti pärast"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> minuti pärast"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 tunni pärast"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> tunni pärast"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"homme"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> päeva pärast"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 s tagasi"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> sekundit tagasi"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 minut tagasi"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> minutit tagasi"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 tund tagasi"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> tundi tagasi"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"eile"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> päeva tagasi"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 sekundi pärast"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> sekundi pärast"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 minuti pärast"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> minuti pärast"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 tunni pärast"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> tunni pärast"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"homme"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> päeva pärast"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"kuupäeval <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"kell <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"aastal <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"nädalat"</string>
<string name="year" msgid="4001118221013892076">"aasta"</string>
<string name="years" msgid="6881577717993213522">"aastat"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekundit"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutit"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 tund"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tundi"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekundit</item>
+ <item quantity="one">1 sekund</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutit</item>
+ <item quantity="one">1 minut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tundi</item>
+ <item quantity="one">1 tund</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Probleem videoga"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"See video ei sobi voogesituseks selles seadmes."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videot ei saa esitada."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Puudub"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Helinad"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tundmatu helin"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"WiFi-võrk on saadaval"</item>
- <item quantity="other" msgid="4192424489168397386">"WiFi-võrgud saadaval"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Avatud WiFi võrk on saadaval"</item>
- <item quantity="other" msgid="7915895323644292768">"Avatud WiFi-võrgud on saadaval"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">WiFi-võrgud on saadaval</item>
+ <item quantity="one">WiFi-võrk on saadaval</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Avatud WiFi-võrgud on saadaval</item>
+ <item quantity="one">Avatud WiFi-võrk on saadaval</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Logige sisse WiFi-võrku"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Logige võrku"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ühendatud meediumiseadmena"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ühendatud kaamerana"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Ühendatud MIDI-seadmena"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ühendatud installijana"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ühendatud USB-lisaseadmega"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Puudutage teisi USB valikuid."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Jäta vahele"</string>
<string name="no_matches" msgid="8129421908915840737">"Vasted puuduvad"</string>
<string name="find_on_page" msgid="1946799233822820384">"Otsige lehelt"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 vaste"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> vastet <xliff:g id="TOTAL">%d</xliff:g>-st</item>
+ <item quantity="one">1 vaste</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Valmis"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB-salvestusruumi eemaldamine ..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD-kaardi eemaldamine ..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Looge PIN-kood piirangute muutmiseks"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-kood ei sobi. Proovige uuesti."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN-kood on liiga lühike. Peab olema vähemalt 4-kohaline."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Proovige uuesti 1 sekundi pärast"</item>
- <item quantity="other" msgid="4730868920742952817">"Proovige uuesti <xliff:g id="COUNT">%d</xliff:g> sekundi pärast"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Proovige uuesti <xliff:g id="COUNT">%d</xliff:g> sekundi pärast</item>
+ <item quantity="one">Proovige uuesti 1 sekundi pärast</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Proovige hiljem uuesti"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Täisekraanilt väljumiseks pühkige ülevalt alla."</string>
<string name="done_label" msgid="2093726099505892398">"Valmis"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Aku kestuse parandamiseks vähendab akusäästja teie seadme toimivust ning piirab vibratsiooni, asukohateenuseid ja suuremat osa taustaandmetest. E-posti, sõnumsidet ja muid sünkroonimisele tuginevaid rakendusi võidakse värskendada ainult siis, kui te need avate.\n\nAkusäästja lülitatakse seadme laadimise ajal automaatselt välja."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kuni seisakuaja lõppemiseni kell <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Kuni puhkeaja lõpuni"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Üheks minutiks (kuni <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d minutiks (kuni <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Üheks tunniks (kuni <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d tunniks (kuni <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Üheks minutiks"</item>
- <item quantity="other" msgid="6924190729213550991">"%d minutiks"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Üheks tunniks"</item>
- <item quantity="other" msgid="5408537517529822157">"%d tunniks"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d minutiks (kuni <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Üheks minutiks (kuni <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d tunniks (kuni <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Üheks tunniks (kuni <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d minutiks</item>
+ <item quantity="one">Üheks minutiks</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d tunniks</item>
+ <item quantity="one">Üheks tunniks</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Määramata ajaks"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Ahendamine"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index e2369ea..0b24d08 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM txartela PUK bidez blokeatuta duzu. Desblokeatzeko, idatzi PUK kodea."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM txartela desblokeatzeko, idatzi PUK2 kodea."</string>
<string name="enablePin" msgid="209412020907207950">"Ezin izan da aldatu. Gaitu SIM edo RUIM txartelaren blokeoa."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"<xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizu SIM txartela blokeatu aurretik."</item>
- <item quantity="other" msgid="7530597808358774740">"<xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela blokeatu aurretik."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela blokeatu aurretik.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela blokeatu aurretik.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Sarrerako deien identifikazio-zerbitzua"</string>
@@ -190,9 +190,9 @@
<string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoaren aukerak"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Pantailaren blokeoa"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Itzali"</string>
- <string name="global_action_bug_report" msgid="7934010578922304799">"Programa-akatsen txostena"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"Sortu programa-akatsen txostena"</string>
- <string name="bugreport_message" msgid="398447048750350456">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira programa-akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
+ <string name="global_action_bug_report" msgid="7934010578922304799">"Akatsen txostena"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"Sortu akatsen txostena"</string>
+ <string name="bugreport_message" msgid="398447048750350456">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Isilik modua"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Soinua DESAKTIBATUTA dago"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Soinua AKTIBATUTA dago"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo telefonoarekin elkarrekintzan aritzeko keinuak egin ditzakezu."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Duela hilabete"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Duela hilabete baino gutxiago"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"duela segundo bat"</item>
- <item quantity="other" msgid="3903706804349556379">"duela <xliff:g id="COUNT">%d</xliff:g> segundo"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"duela minutu bat"</item>
- <item quantity="other" msgid="2176942008915455116">"duela <xliff:g id="COUNT">%d</xliff:g> minutu"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Duela ordubete"</item>
- <item quantity="other" msgid="2467273239587587569">"duela <xliff:g id="COUNT">%d</xliff:g> ordu"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Azken <xliff:g id="COUNT_1">%d</xliff:g> egunetan</item>
+ <item quantity="one">Azken <xliff:g id="COUNT_0">%d</xliff:g> egunean</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Azken hilabetea"</string>
<string name="older" msgid="5211975022815554840">"Zaharragoa"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"atzo"</item>
- <item quantity="other" msgid="2479586466153314633">"Duela <xliff:g id="COUNT">%d</xliff:g> egun"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"segundo bat barru"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> segundo barru"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"Minutu bat barru"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> minutu barru"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"Ordubete barru"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> ordu barru"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"bihar"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> egun barru"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"duela segundo bat"</item>
- <item quantity="other" msgid="3699169366650930415">"duela <xliff:g id="COUNT">%d</xliff:g> segundo"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"duela minutu bat"</item>
- <item quantity="other" msgid="851164968597150710">"duela <xliff:g id="COUNT">%d</xliff:g> minutu"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"duela ordubete"</item>
- <item quantity="other" msgid="6889970745748538901">"duela <xliff:g id="COUNT">%d</xliff:g> ordu"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"atzo"</item>
- <item quantity="other" msgid="3453342639616481191">"Duela <xliff:g id="COUNT">%d</xliff:g> egun"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"segundo bat barru"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> segundo barru"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"minutu bat barru"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> minutu barru"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ordubete barru"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> ordu barru"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"bihar"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> egun barru"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"data: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"urtea: <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"aste"</string>
<string name="year" msgid="4001118221013892076">"urte"</string>
<string name="years" msgid="6881577717993213522">"urte"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundo"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minutu"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutu"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ordu"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ordu"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundo</item>
+ <item quantity="one">Segundo bat</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutu</item>
+ <item quantity="one">Minutu bat</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ordu</item>
+ <item quantity="one">Ordubete</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Bideoak arazoren bat du"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Bideo hau ezin da gailuan zuzenean erreproduzitu."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ezin da bideoa erreproduzitu."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Bat ere ez"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuak"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tonu ezezaguna"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi sarea erabilgarri"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi sareak erabilgarri"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Wi-Fi sare irekia erabilgarri"</item>
- <item quantity="other" msgid="7915895323644292768">"Wi-Fi sare irekiak erabilgarri"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi sareak erabilgarri</item>
+ <item quantity="one">Wi-Fi sarea erabilgarri</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Wi-Fi sare irekiak erabilgarri</item>
+ <item quantity="one">Wi-Fi sare irekia erabilgarri</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Hasi saioa Wi-Fi sarean"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Hasi saioa sarean"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Ados"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Multimedia-gailu gisa konektatua"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera gisa konektatua"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI gailu gisa konektatu da"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Instalatzaile gisa konektatua"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB osagarri batera konektatuta"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Ukitu beste USB aukera batzuk ikusteko."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Saltatu"</string>
<string name="no_matches" msgid="8129421908915840737">"Ez dago emaitzarik"</string>
<string name="find_on_page" msgid="1946799233822820384">"Aurkitu orri honetan"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"Emaitza bat"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">Emaitza bat</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Eginda"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB memoria desmuntatzen…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD txartela desmuntatzen…"</string>
@@ -1665,7 +1605,7 @@
<string name="media_route_status_available" msgid="6983258067194649391">"Erabilgarri"</string>
<string name="media_route_status_not_available" msgid="6739899962681886401">"Ez dago erabilgarri"</string>
<string name="media_route_status_in_use" msgid="4533786031090198063">"Abian"</string>
- <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Pantaila barneratua"</string>
+ <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Pantaila integratua"</string>
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI pantaila"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>. gainjartzea"</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>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Konfiguratu debekuak aldatu ahal izateko idatzi beharko den PIN kodea"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINak ez datoz bat. Saiatu berriro."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PINa laburregia da. 4 digitu izan behar ditu gutxienez."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Saiatu berriro segundo bat igarotakoan"</item>
- <item quantity="other" msgid="4730868920742952817">"Saiatu berriro <xliff:g id="COUNT">%d</xliff:g> segundo igarotakoan"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Saiatu berriro <xliff:g id="COUNT">%d</xliff:g> segundo igarotakoan</item>
+ <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_mode_confirmation" msgid="7227416894979047467">"Pantaila osotik irteteko, pasatu hatza goitik behera."</string>
<string name="done_label" msgid="2093726099505892398">"Eginda"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Bateriak gehiago iraun dezan, bateria-aurrezleak gailuaren funtzionamendua, dardara, kokapen-zerbitzuak eta atzeko planoko datuen erabilera gehiena mugatzen ditu. Posta elektronikoa, mezuak eta sinkronizatzen diren gainerako zerbitzuak ez dira eguneratuko ireki ezean.\n\nGailua kargatzen ezarri orduko desaktibatzen da bateria-aurrezlea."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte iraungo du jarduerarik gabeko aldiak"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Jarduerarik gabeko denbora amaitu arte"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Minutu batez (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> arte)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d minutuz (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> arte)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Ordubetez (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> arte)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d orduz (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> arte)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Minutu batez"</item>
- <item quantity="other" msgid="6924190729213550991">"%d minutuz"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Ordubetez"</item>
- <item quantity="other" msgid="5408537517529822157">"%d orduz"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d minutuz (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> arte)</item>
+ <item quantity="one">Minutu batez (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> arte)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d orduz (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> arte)</item>
+ <item quantity="one">Ordubetez (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> arte)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d minutuz</item>
+ <item quantity="one">Minutu batez</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d orduz</item>
+ <item quantity="one">Ordubetez</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Mugagabea"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Tolestu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 547f432..2e040e33 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"سیم کارت شما با PUK قفل شده است. کد PUK را برای بازگشایی آن بنویسید."</string>
<string name="needPuk2" msgid="4526033371987193070">"PUK2 را برای بازگشایی قفل سیم کارت بنویسید."</string>
<string name="enablePin" msgid="209412020907207950">"ناموفق بود، قفل سیم/RUIM را فعال کنید."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"<xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیم کارت قفل میشود."</item>
- <item quantity="other" msgid="7530597808358774740">"<xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیم کارت قفل میشود."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"شناسه تماس گیرنده ورودی"</string>
@@ -1131,73 +1131,12 @@
<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">"۱ ماه قبل"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل از ۱ ماه گذشته"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"۱ ثانیه قبل"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> ثانیه قبل"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"۱ دقیقه قبل"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> دقیقه قبل"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"۱ ساعت قبل"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ساعت قبل"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> روز قبل</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> روز قبل</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"ماه گذشته"</string>
<string name="older" msgid="5211975022815554840">"قدیمی تر"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ديروز"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> روز قبل"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"در ۱ ثانیه"</item>
- <item quantity="other" msgid="1241926116443974687">"در <xliff:g id="COUNT">%d</xliff:g> ثانیه"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"در ۱ دقیقه"</item>
- <item quantity="other" msgid="3330713936399448749">"در <xliff:g id="COUNT">%d</xliff:g> دقیقه"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"در ۱ ساعت"</item>
- <item quantity="other" msgid="547290677353727389">"در <xliff:g id="COUNT">%d</xliff:g> ساعت"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"فردا"</item>
- <item quantity="other" msgid="5109449375100953247">"در <xliff:g id="COUNT">%d</xliff:g> روز"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"۱ ثانیه قبل"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> ثانیه قبل"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"۱ دقیقه قبل"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> دقیقه قبل"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"۱ ساعت قبل"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ساعت قبل"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ديروز"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> روز قبل"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"در ۱ ثانیه"</item>
- <item quantity="other" msgid="5495880108825805108">"در <xliff:g id="COUNT">%d</xliff:g> ثانیه"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"در ۱ دقیقه"</item>
- <item quantity="other" msgid="4216113292706568726">"در <xliff:g id="COUNT">%d</xliff:g> دقیقه"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"در ۱ ساعت"</item>
- <item quantity="other" msgid="3705373766798013406">"در <xliff:g id="COUNT">%d</xliff:g> ساعت"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"فردا"</item>
- <item quantity="other" msgid="2973062968038355991">"در <xliff:g id="COUNT">%d</xliff:g> روز"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"در <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"در <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"در <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"هفته"</string>
<string name="year" msgid="4001118221013892076">"سال"</string>
<string name="years" msgid="6881577717993213522">"سال"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"۱ ثانیه"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ثانیه"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"۱ دقیقه"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> دقیقه"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"۱ ساعت"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ساعت"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ثانیه</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ثانیه</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> دقیقه</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> دقیقه</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ساعت</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"هیچکدام"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"آهنگهای زنگ"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"آهنگ زنگ ناشناس"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"شبکه Wi-Fi موجود است"</item>
- <item quantity="other" msgid="4192424489168397386">"شبکههای Wi-Fi موجود هستند"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"شبکه Wi-Fi موجود را باز کنید"</item>
- <item quantity="other" msgid="7915895323644292768">"شبکههای Wi-Fi موجود را باز کنید"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">شبکه Wi-Fi در دسترس</item>
+ <item quantity="other">شبکه Wi-Fi در دسترس</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">شبکه Wi-Fi باز در دسترس</item>
+ <item quantity="other">شبکه Wi-Fi باز در دسترس</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ورود به شبکه Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ورود به شبکه"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده بهعنوان دستگاه رسانهای"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده بهعنوان دوربین"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"به عنوان یک دستگاه MIDI متصل شد"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده بهعنوان نصب کننده"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"به یک وسیله جانبی USB وصل شده است"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"برای سایر گزینههای USB لمس کنید."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 مورد منطبق"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"انجام شد"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"در حال لغو نصب حافظهٔ USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"در حال لغو نصب کارت SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"یک پین برای تغییر محدودیتها ایجاد کنید"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"پینها مطابقت ندارند. دوباره امتحان کنید."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"پین بیش از حد کوتاه است. باید حداقل ۴ رقم باشد."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"امتحان پس از ۱ ثانیه"</item>
- <item quantity="other" msgid="4730868920742952817">"امتحان پس از <xliff:g id="COUNT">%d</xliff:g> ثانیه"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ثانیه دیگر دوباره امتحان کنید</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ثانیه دیگر دوباره امتحان کنید</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"بعداً دوباره امتحان کنید"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"برای خروج از حالت تمام صفحه، انگشت خود را به تندی از بالای صفحه به پایین بکشید."</string>
<string name="done_label" msgid="2093726099505892398">"انجام شد"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"برای کمک به بهبود ماندگاری باتری، ابزار صرفهجویی در مصرف باتری عملکرد دستگاهتان را کاهش میدهد و لرزش، سرویسهای مبتنی بر مکان، و دسترسی به اکثر دادهها در پسزمینه را محدود میکند. ایمیل، پیامرسانی و برنامههای دیگری که به همگامسازی متکی هستند، تا زمانی که آنها را باز نکنید نمیتوانند بهروز شوند.\n\nابزار صرفهجویی در مصرف باتری به صورت خودکار در هنگام شارژ شدن دستگاه خاموش میشود."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"تا زمانی که زمان استراحت در <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> به پایان برسد"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"تا زمان اتمام فرویش"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"به مدت یک دقیقه (تا <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"به مدت %1$d دقیقه (تا <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"به مدت یک ساعت (تا <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"به مدت %1$d ساعت (تا <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"برای یک دقیقه"</item>
- <item quantity="other" msgid="6924190729213550991">"برای %d دقیقه"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"برای یک ساعت"</item>
- <item quantity="other" msgid="5408537517529822157">"برای %d ساعت"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">به مدت %1$d دقیقه (تا <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">به مدت %1$d دقیقه (تا <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">به مدت %1$d ساعت (تا <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">به مدت %1$d ساعت (تا <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">به مدت %d دقیقه</item>
+ <item quantity="other">به مدت %d دقیقه</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">به مدت %d ساعت</item>
+ <item quantity="other">به مدت %d ساعت</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"تا <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"نامحدود"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"کوچک کردن"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e262015..ce9d6ee 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM-korttisi on PUK-lukittu. Poista lukitus antamalla PUK-koodi."</string>
<string name="needPuk2" msgid="4526033371987193070">"Pura SIM-kortin esto antamalla PUK2-koodi."</string>
<string name="enablePin" msgid="209412020907207950">"Epäonnistui, ota SIM-/RUIM-lukitus käyttöön."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortti lukitaan."</item>
- <item quantity="other" msgid="7530597808358774740">"Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortti lukitaan."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Sinulla on <xliff:g id="NUMBER_1">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortti lukitaan.</item>
+ <item quantity="one">Sinulla on <xliff:g id="NUMBER_0">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortti lukitaan.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI-koodi"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Soittajan tunnus"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> haluaa ottaa Tutustu koskettamalla -ominaisuuden käyttöön. Kun Tutustu koskettamalla on käytössä, näet tai kuulet kuvauksen sormen alla olevista kohteista ja voit käyttää puhelinta sormieleiden avulla."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"kuukausi sitten"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Yli kuukausi sitten"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 sekunti sitten"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sekuntia sitten"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuutti sitten"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minuuttia sitten"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 tunti sitten"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> tuntia sitten"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Edellisten <xliff:g id="COUNT_1">%d</xliff:g> päivän aikana</item>
+ <item quantity="one">Edellisen <xliff:g id="COUNT_0">%d</xliff:g> päivän aikana</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Viime kuussa"</string>
<string name="older" msgid="5211975022815554840">"Vanhemmat"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"eilen"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> päivää sitten"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 sekunnin kuluttua"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> sekunnin kuluttua"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 minuutin kuluttua"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> minuutin kuluttua"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 tunnin kuluttua"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> tunnin kuluttua"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"huomenna"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> päivän kuluttua"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 s sitten"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> s sitten"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min sitten"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> min sitten"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 tunti sitten"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> tuntia sitten"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"eilen"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> päivää sitten"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 s kuluttua"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> sekunnin kuluttua"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 min kuluttua"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> min kuluttua"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 tunnin kuluttua"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> tunnin kuluttua"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"huomenna"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> päivän kuluttua"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"päivä: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"klo <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"vuonna <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"viikkoa"</string>
<string name="year" msgid="4001118221013892076">"vuosi"</string>
<string name="years" msgid="6881577717993213522">"vuotta"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekunti"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekuntia"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuutti"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuuttia"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 tunti"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> tuntia"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekuntia</item>
+ <item quantity="one">1 sekunti</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuuttia</item>
+ <item quantity="one">1 minuutti</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> tuntia</item>
+ <item quantity="one">1 tunti</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video-ongelma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Tätä videota ei voi suoratoistaa tällä laitteella."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Videota ei voida toistaa."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ei mitään"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Soittoäänet"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Tuntematon soittoääni"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi-verkko käytettävissä"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi-verkkoja käytettävissä"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Avoin Wi-Fi-verkko käytettävissä"</item>
- <item quantity="other" msgid="7915895323644292768">"Avoimia Wi-Fi-verkkoja käytettävissä"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi-verkkoja käytettävissä</item>
+ <item quantity="one">Wi-Fi-verkko käytettävissä</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Avoimia Wi-Fi-verkkoja käytettävissä</item>
+ <item quantity="one">Avoin Wi-Fi-verkko käytettävissä</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Kirjaudu Wi-Fi-verkkoon"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Kirjaudu verkkoon"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Kytketty medialaitteena"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kytketty kamerana"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Yhdistetty MIDI-laitteeseen"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Kytketty asennusohjelmana"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Liitetty USB-laitteeseen"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Käytä muita USB-vaihtoehtoja koskettamalla."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ohita"</string>
<string name="no_matches" msgid="8129421908915840737">"Ei tuloksia"</string>
<string name="find_on_page" msgid="1946799233822820384">"Etsi sivulta"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 tulos"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 tulos</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Valmis"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Poistetaan USB-tallennustilaa käytöstä..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Poistetaan SD-korttia käytöstä..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Luo uusi PIN-koodi rajoitusten muokkaamista varten"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-koodit eivät vastaa toisiaan. Yritä uudelleen."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN-koodi on liian lyhyt. Vähimmäispituus on neljä merkkiä."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Yritä uud. 1 s kul."</item>
- <item quantity="other" msgid="4730868920742952817">"Yritä uud. <xliff:g id="COUNT">%d</xliff:g> s kul."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Yritä uudelleen <xliff:g id="COUNT">%d</xliff:g> sekunnin kuluttua</item>
+ <item quantity="one">Yritä uudelleen 1 sekunnin kuluttua</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Yritä myöhemmin uudelleen"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Poistu koko näytön tilasta pyyhkäisemällä alas."</string>
<string name="done_label" msgid="2093726099505892398">"Valmis"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Jos haluat parantaa akun kestoa, virransäästö vähentää laitteesi suorituskykyä ja rajoittaa värinää, sijaintipalveluita ja useimpia taustatietoja. Sähköposti, viestit ja muut synkronointiin perustuvat sovellukset eivät välttämättä päivity, ellet avaa niitä.\n\nVirransäästö poistuu käytöstä automaattisesti, kun laitteesi latautuu."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Käyttökatkos päättyy klo <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Vapaa-aikasi päättymiseen saakka"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Yksi minuutti (kunnes kello on <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d minuuttia (kunnes kello on <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Yksi tunti (kunnes kello on <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d tuntia (kunnes kello on <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Minuutiksi"</item>
- <item quantity="other" msgid="6924190729213550991">"%d minuutiksi"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Tunniksi"</item>
- <item quantity="other" msgid="5408537517529822157">"%d tunniksi"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d minuutiksi (kunnes kello on <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Yhdeksi minuutiksi (kunnes kello on <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d tunniksi (kunnes kello on <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Yhdeksi tunniksi (kunnes kello on <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d minuutiksi</item>
+ <item quantity="one">Minuutiksi</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d tunniksi</item>
+ <item quantity="one">Tunniksi</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kunnes kello on <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Toistaiseksi"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Kutista"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9a9ab32..aa10dd6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller."</string>
<string name="needPuk2" msgid="4526033371987193070">"Saisissez la clé PUK2 pour débloquer la carte SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Opération infructueuse. Activez le verrouillage SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée."</item>
- <item quantity="other" msgid="7530597808358774740">"Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative(s) avant que votre carte SIM soit verrouillée."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée.</item>
+ <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM soit verrouillée.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"Code IIEM"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Numéro de l\'appelant (entrant)"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> souhaite activer la fonctionnalité \"Explorer au toucher\". Lorsque celle-ci est activée, vous pouvez entendre ou voir les descriptions des éléments que vous sélectionnez, ou bien interagir avec le téléphone en effectuant certains gestes."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Il y a 1 mois"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Il y a plus d\'un mois"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"il y a 1 seconde"</item>
- <item quantity="other" msgid="3903706804349556379">"Il y a <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Il y a 1 minute"</item>
- <item quantity="other" msgid="2176942008915455116">"Il y a <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Il y a 1 heure"</item>
- <item quantity="other" msgid="2467273239587587569">"il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
+ <item quantity="other">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Le mois dernier"</string>
<string name="older" msgid="5211975022815554840">"Précédent"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"hier"</item>
- <item quantity="other" msgid="2479586466153314633">"il y a <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"dans 1 seconde"</item>
- <item quantity="other" msgid="1241926116443974687">"dans <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"dans 1 minute"</item>
- <item quantity="other" msgid="3330713936399448749">"dans <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"dans 1 heure"</item>
- <item quantity="other" msgid="547290677353727389">"dans <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"demain"</item>
- <item quantity="other" msgid="5109449375100953247">"dans <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"il y a 1 seconde"</item>
- <item quantity="other" msgid="3699169366650930415">"il y a <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"il y a 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"il y a <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Il y a 1 h"</item>
- <item quantity="other" msgid="6889970745748538901">"il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"hier"</item>
- <item quantity="other" msgid="3453342639616481191">"il y a <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"dans 1 seconde"</item>
- <item quantity="other" msgid="5495880108825805108">"dans <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"dans 1 minute"</item>
- <item quantity="other" msgid="4216113292706568726">"dans <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"dans 1 heure"</item>
- <item quantity="other" msgid="3705373766798013406">"dans <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"demain"</item>
- <item quantity="other" msgid="2973062968038355991">"dans <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"le <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"en <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semaines"</string>
<string name="year" msgid="4001118221013892076">"an"</string>
<string name="years" msgid="6881577717993213522">"ans"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>minutes"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 heure"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> seconde</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> secondes</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutes</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> heure</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> heures</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problème vidéo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Impossible de lire cette vidéo en continu sur cet appareil."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossible de lire la vidéo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Sonnerie inconnue"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Réseau Wi-Fi disponible"</item>
- <item quantity="other" msgid="4192424489168397386">"Réseaux Wi-Fi disponibles"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Réseau Wi-Fi ouvert disponible"</item>
- <item quantity="other" msgid="7915895323644292768">"Réseaux Wi-Fi ouverts disponibles"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Réseau Wi-Fi à proximité</item>
+ <item quantity="other">Réseaux Wi-Fi à proximité</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Réseau Wi-Fi ouvert à proximité</item>
+ <item quantity="other">Réseaux Wi-Fi ouverts à proximité</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Se connecter au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'app. multimédia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connecté en tant qu\'appareil MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connecté à un accessoire USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Appuyez pour accéder aux autres options USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Passer"</string>
<string name="no_matches" msgid="8129421908915840737">"Aucune partie"</string>
<string name="find_on_page" msgid="1946799233822820384">"Rechercher sur la page"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 correspondance"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Terminé"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Désinstallation de la mémoire de stockage USB en cours…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Désinstallation de la carte SD en cours…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Créez un NIP pour modifier les restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Les NIP ne correspondent pas. Essayez à nouveau."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Le NIP est trop court. Il doit comporter au moins 4 chiffres."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Réessayer dans 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Réessayer dans <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
+ <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Réessayez plus tard"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Balayez vers le bas pour quitter le mode plein écran"</string>
<string name="done_label" msgid="2093726099505892398">"Terminé"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Pour améliorer l\'autonomie de la pile, la fonction d\'économie d\'énergie réduit les performances de votre appareil et limite la vibration, les services de localisation ainsi que la plupart des données en arrière-plan. Les applications Courriel, Messages et d\'autres qui reposent sur la synchronisation ne peuvent pas se mettre à jour, sauf si vous les ouvrez. \n\n L\'économiseur d\'énergie se désactive automatiquement lorsque votre appareil est en charge."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Jusqu\'à la fin du temps d\'arrêt"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Pendant une minute (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Pendant une heure (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
- <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
- <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Pendant %d minute</item>
+ <item quantity="other">Pendant %d minutes</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Pendant %d heure</item>
+ <item quantity="other">Pendant %d heures</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Réduire"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4ba1aae..0c7e7ba 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller."</string>
<string name="needPuk2" msgid="4526033371987193070">"Saisissez la clé PUK2 pour débloquer la carte SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Échec de l\'opération. Veuillez activer le verrouillage de la carte SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée."</item>
- <item quantity="other" msgid="7530597808358774740">"Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée.</item>
+ <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"Code IMEI"</string>
<string name="meid" msgid="4841221237681254195">"Code MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Numéro de l\'appelant (entrant)"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> souhaite activer la fonctionnalité \"Explorer au toucher\". Lorsque celle-ci est activée, vous pouvez entendre ou voir les descriptions des éléments que vous sélectionnez, ou bien interagir avec le téléphone en effectuant certains gestes."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Il y a 1 mois"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Il y a plus d\'un mois"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Il y a 1 seconde"</item>
- <item quantity="other" msgid="3903706804349556379">"Il y a <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Il y a 1 minute"</item>
- <item quantity="other" msgid="2176942008915455116">"Il y a <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"il y a 1 heure"</item>
- <item quantity="other" msgid="2467273239587587569">"Il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Le dernier jour (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
+ <item quantity="other">Les <xliff:g id="COUNT_1">%d</xliff:g> derniers jours</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Le mois dernier"</string>
<string name="older" msgid="5211975022815554840">"Préc."</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"hier"</item>
- <item quantity="other" msgid="2479586466153314633">"Il y a <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"dans 1 seconde"</item>
- <item quantity="other" msgid="1241926116443974687">"dans <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"dans 1 minute"</item>
- <item quantity="other" msgid="3330713936399448749">"dans <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"dans 1 heure"</item>
- <item quantity="other" msgid="547290677353727389">"dans <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"demain"</item>
- <item quantity="other" msgid="5109449375100953247">"dans <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"il y a 1 seconde"</item>
- <item quantity="other" msgid="3699169366650930415">"il y a <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"il y a 1 minute"</item>
- <item quantity="other" msgid="851164968597150710">"il y a <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"il y a 1 heure"</item>
- <item quantity="other" msgid="6889970745748538901">"Il y a <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"hier"</item>
- <item quantity="other" msgid="3453342639616481191">"Il y a <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"dans 1 seconde"</item>
- <item quantity="other" msgid="5495880108825805108">"dans <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"dans 1 minute"</item>
- <item quantity="other" msgid="4216113292706568726">"dans <xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"dans 1 heure"</item>
- <item quantity="other" msgid="3705373766798013406">"dans <xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"demain"</item>
- <item quantity="other" msgid="2973062968038355991">"dans <xliff:g id="COUNT">%d</xliff:g> jours"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"le <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"à <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"en <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semaines"</string>
<string name="year" msgid="4001118221013892076">"année"</string>
<string name="years" msgid="6881577717993213522">"années"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondes"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minute"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutes"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 heure"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> heures"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> seconde</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> secondes</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutes</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> heure</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> heures</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problème vidéo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Impossible de lire cette vidéo en streaming sur cet appareil."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossible de lire la vidéo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Aucun"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Sonnerie inconnue"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Réseau Wi-Fi disponible"</item>
- <item quantity="other" msgid="4192424489168397386">"Réseaux Wi-Fi disponibles"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Réseau Wi-Fi ouvert disponible"</item>
- <item quantity="other" msgid="7915895323644292768">"Réseaux Wi-Fi ouverts disponibles"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Réseau Wi-Fi disponible</item>
+ <item quantity="other">Réseaux Wi-Fi disponibles</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Réseau Wi-Fi ouvert disponible</item>
+ <item quantity="other">Réseaux Wi-Fi ouverts disponibles</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Se connecter au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'appareil multimédia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connecté en tant qu\'appareil MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connecté à un accessoire USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Appuyez ici pour accéder aux autres options USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ignorer"</string>
<string name="no_matches" msgid="8129421908915840737">"Aucune correspondance"</string>
<string name="find_on_page" msgid="1946799233822820384">"Rechercher sur la page"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 correspondance"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"OK"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Désinstallation de la mémoire de stockage USB en cours…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Désinstallation de la carte SD en cours…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Créer un code PIN pour modifier les restrictions"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Les codes PIN ne correspondent pas. Veuillez réessayer."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Le code PIN est trop court. Il doit comporter au moins 4 chiffres."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Réessayer dans 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Réessayer dans <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
+ <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Veuillez réessayer ultérieurement."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Faites glisser le doigt vers le bas pour quitter le mode plein écran."</string>
<string name="done_label" msgid="2093726099505892398">"OK"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Pour améliorer l\'autonomie de la batterie, l\'économiseur de batterie réduit les performances de votre appareil, et il désactive le vibreur, les services de localisation et la plupart des données en arrière-plan. La messagerie électronique, les SMS/MMS et les autres applications basées sur la synchronisation ne sont mises à jour que si vous les ouvrez.\n\nL\'économiseur de batterie s\'éteint automatiquement lorsque votre appareil est en charge."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Jusqu\'à la fin du temps d\'arrêt"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Pendant une minute (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Pendant une heure (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
- <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
- <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Pendant %d minute</item>
+ <item quantity="other">Pendant %d minutes</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Pendant %d heure</item>
+ <item quantity="other">Pendant %d heures</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Réduire"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 26629c1..babbb67 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"A tarxeta SIM está bloqueada con código PUK. Escribe o código PUK para desbloqueala."</string>
<string name="needPuk2" msgid="4526033371987193070">"Escribe o código PUK2 para desbloquear a tarxeta SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Non é correcto. Activa o bloqueo da SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Quédache <xliff:g id="NUMBER">%d</xliff:g> intento antes de que se bloquee a SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"Quédanche <xliff:g id="NUMBER">%d</xliff:g> intentos antes de que se bloquee a SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Quédanche <xliff:g id="NUMBER_1">%d</xliff:g> intentos antes de que se bloquee a SIM.</item>
+ <item quantity="one">Quédache <xliff:g id="NUMBER_0">%d</xliff:g> intento antes de que se bloquee a SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID de chamada entrante"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quere activar a exploración táctil. Cando a exploración táctil estea activada, poderás escoitar ou ver descricións do contido seleccionado ou realizar xestos para interactuar co teléfono."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Hai 1 mes"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Hai máis de 1 mes"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"hai 1 segundo"</item>
- <item quantity="other" msgid="3903706804349556379">"hai <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"hai 1 minuto"</item>
- <item quantity="other" msgid="2176942008915455116">"hai <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Hai 1 hora"</item>
- <item quantity="other" msgid="2467273239587587569">"hai <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> días</item>
+ <item quantity="one">Último <xliff:g id="COUNT_0">%d</xliff:g> día</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"O mes pasado"</string>
<string name="older" msgid="5211975022815554840">"Antes"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"onte"</item>
- <item quantity="other" msgid="2479586466153314633">"Hai <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"en 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"en <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"En 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"en <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"En 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"En <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"mañá"</item>
- <item quantity="other" msgid="5109449375100953247">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"hai 1 s"</item>
- <item quantity="other" msgid="3699169366650930415">"hai <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"hai 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"hai <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"hai 1 hora"</item>
- <item quantity="other" msgid="6889970745748538901">"hai <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"onte"</item>
- <item quantity="other" msgid="3453342639616481191">"Hai <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"en 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"en <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"en 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"en <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"en 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"en <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"mañá"</item>
- <item quantity="other" msgid="2973062968038355991">"en <xliff:g id="COUNT">%d</xliff:g> días"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"o <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ás <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"no <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"ano"</string>
<string name="years" msgid="6881577717993213522">"anos"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">Un segundo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ <item quantity="one">Un minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ <item quantity="one">Unha hora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Hai un problema co vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo non se pode transmitir no dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Non se pode reproducir este vídeo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ningún"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tons de chamada"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Ton de chamada descoñecido"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Rede Wi-Fi dispoñible"</item>
- <item quantity="other" msgid="4192424489168397386">"Redes Wi-Fi dispoñibles"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Abrir a rede Wi-Fi dispoñible"</item>
- <item quantity="other" msgid="7915895323644292768">"Abrir as redes Wi-Fi dispoñibles"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Redes wifi dispoñibles</item>
+ <item quantity="one">Rede wifi dispoñible</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Abrir redes wifi dispoñibles</item>
+ <item quantity="one">Abrir rede wifi dispoñible</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Inicia sesión na rede wifi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Inicia sesión na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como dispositivo multimedia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como unha cámara"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectado como dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como instalador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectado a un accesorio USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toca para acceder a outras opcións de USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Omitir"</string>
<string name="no_matches" msgid="8129421908915840737">"Non hai coincidencias"</string>
<string name="find_on_page" msgid="1946799233822820384">"Buscar na páxina"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 coincidencia"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">Unha coincidencia</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Feito"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Desactivando o almacenamento USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Desactivando a tarxeta SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crea un PIN para modificar as restricións"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PIN non coinciden. Téntao de novo."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é demasiado curto. Debe conter polo menos 4 díxitos."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Téntao de novo dentro de 1 segundo"</item>
- <item quantity="other" msgid="4730868920742952817">"Téntao de novo dentro de <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Téntao de novo en <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">Téntao de novo dentro nun segundo</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Téntao de novo máis tarde"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Pasa o dedo cara abaixo desde a parte superior para saír da pantalla completa."</string>
<string name="done_label" msgid="2093726099505892398">"Feito"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Para axudar a mellorar a duración da batería, a función aforro de batería reduce o rendemento do teu dispositivo e limita a vibración, os servizos de localización e a maioría dos datos en segundo plano. É posible que o correo electrónico, as mensaxes e outras aplicacións que dependen da sincronización non se actualicen a menos que os abras. \n\nA función aforro de batería desactívase automaticamente cando pos a cargar o teu dispositivo."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Ata que remate o tempo de inactividade ás <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Ata que remate o tempo de inactividade"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Durante un minuto (ata as <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Durante %1$d minutos (ata as <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Durante unha hora (ata as <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Durante %1$d horas (ata as <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Durante unha hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Durante %1$d minutos (ata as <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante un minuto (ata as <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Durante %1$d horas (ata as <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante unha hora (ata as <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Durante %d minutos</item>
+ <item quantity="one">Durante un minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Durante %d horas</item>
+ <item quantity="one">Durante unha hora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Contraer"</string>
diff --git a/core/res/res/values-h320dp/bools.xml b/core/res/res/values-h320dp/bools.xml
new file mode 100644
index 0000000..8dbc2e1
--- /dev/null
+++ b/core/res/res/values-h320dp/bools.xml
@@ -0,0 +1,21 @@
+<?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>
+ <bool name="allow_stacked_button_bar">true</bool>
+</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 2ebee8f..1f0381b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"आपका सिम कार्ड PUK लॉक किया गया है. इसे अनलॉक करने के लिए PUK कोड लिखें."</string>
<string name="needPuk2" msgid="4526033371987193070">"सिम कार्ड अनब्लॉक करने के लिए PUK2 लिखें."</string>
<string name="enablePin" msgid="209412020907207950">"असफल, सिम//RUIM लॉक सक्षम करें."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"सिम के लॉक हो जाने से पहले आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष है."</item>
- <item quantity="other" msgid="7530597808358774740">"सिम के लॉक हो जाने से पहले आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष हैं."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"इनकमिंग कॉलर ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 सेकंड पहले"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> सेकंड पहले"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 मिनट पहले"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> मिनट पहले"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 घंटे पहले"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> घंटे पहले"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">पिछले <xliff:g id="COUNT_1">%d</xliff:g> दिनों में</item>
+ <item quantity="other">पिछले <xliff:g id="COUNT_1">%d</xliff:g> दिनों में</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"पिछला माह"</string>
<string name="older" msgid="5211975022815554840">"इससे पुराना"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"बीता कल"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> दिन पहले"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 सेकंड में"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> सेकंड में"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 मिनट में"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> मिनट में"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 घंटे में"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> घंटे में"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"आने वाला कल"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> दिन में"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 सेकंड पहले"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> सेकंड पहले"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 मिनट पहले"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> मिनट पहले"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 घंटे पहले"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> घंटे पहले"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"बीता कल"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> दिन पहले"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 सेकंड में"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> सेकंड में"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 मिनट में"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> मिनट में"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 घंटे में"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> घंटे में"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"आने वाला कल"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> दिन में"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> को"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> पर"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> में"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"सप्ताह"</string>
<string name="year" msgid="4001118221013892076">"वर्ष"</string>
<string name="years" msgid="6881577717993213522">"वर्ष"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 सेकंड"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> सेकंड"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 मिनट"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> मिनट"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 घंटा"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> घंटे"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंड</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकंड</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> मिनट</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> मिनट</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> घंटे</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिंगटोन"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"वाई-फ़ाई नेटवर्क उपलब्ध"</item>
- <item quantity="other" msgid="4192424489168397386">"वाई-फ़ाई नेटवर्क उपलब्ध"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"उपलब्ध वाई-फ़ाई नेटवर्क खोलें"</item>
- <item quantity="other" msgid="7915895323644292768">"खुले वाई-फ़ाई नेटवर्क उपलब्ध है"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">वाई-फ़ाई नेटवर्क उपलब्ध</item>
+ <item quantity="other">वाई-फ़ाई नेटवर्क उपलब्ध</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">खुले वाई-फ़ाई नेटवर्क उपलब्ध</item>
+ <item quantity="other">खुले वाई-फ़ाई नेटवर्क उपलब्ध</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"वाई-फ़ाई नेटवर्क में प्रवेश करें"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"नेटवर्क में प्रवेश करें"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ठीक है"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"किसी मीडिया डिवाइस के रूप में कनेक्ट किया गया"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"कैमरे के रूप में कनेक्ट करें"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI डिवाइस के रूप में कनेक्ट है"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"किसी इंस्टॉलर के रूप में कनेक्ट किया गया"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB सहायक सामग्री से कनेक्ट किया गया"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"अन्य USB विकल्पों के लिए स्पर्श करें."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 मिलान"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> में से <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> में से <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> में से <xliff:g id="INDEX">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"पूर्ण"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB मेमोरी अनमाउंट हो रहा है…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD कार्ड अनमाउंट किया जा रहा है…"</string>
@@ -1757,8 +1697,8 @@
<string name="mediasize_iso_c10" msgid="5040764293406765584">"ISO C10"</string>
<string name="mediasize_na_letter" msgid="2841414839888344296">"लेटर"</string>
<string name="mediasize_na_gvrnmt_letter" msgid="5295836838862962809">"गवर्नमेंट लेटर"</string>
- <string name="mediasize_na_legal" msgid="8621364037680465666">"लीगल"</string>
- <string name="mediasize_na_junior_legal" msgid="3309324162155085904">"जूनियर लीगल"</string>
+ <string name="mediasize_na_legal" msgid="8621364037680465666">"वैधानिक"</string>
+ <string name="mediasize_na_junior_legal" msgid="3309324162155085904">"जूनियर वैधानिक"</string>
<string name="mediasize_na_ledger" msgid="5567030340509075333">"लेजर"</string>
<string name="mediasize_na_tabloid" msgid="4571735038501661757">"टेबलॉइड"</string>
<string name="mediasize_na_index_3x5" msgid="5182901917818625126">"इंडेक्स कार्ड 3x5"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN बहुत छोटा है. कम से कम 4 अंकों का होना चाहिए."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 सेकंड में पुन: प्रयास करें"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> सेकंड में पुन: प्रयास करें"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंड में पुन: प्रयास करें</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकंड में पुन: प्रयास करें</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"बाद में फिर से प्रयास करें"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"पूर्ण स्क्रीन से बाहर आने के लिए ऊपर से नीचे स्वाइप करें."</string>
<string name="done_label" msgid="2093726099505892398">"पूर्ण"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"बैटरी जीवन काल को बेहतर बनाने में सहायता के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को कम कर देता है और कंपन, स्थान सेवाओं और अधिकांश पृष्ठभूमि डेटा को सीमित कर देता है. हो सकता है कि ईमेल, संदेश सेवा तथा समन्वयन पर आधारित अन्य ऐप्स तब तक ना खुलें जब तक कि आप उन्हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"जब तक कि <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> बजे आपका डाउनटाइम समाप्त न हो"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"आपका बंद रहने का समय समाप्त होने तक"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"एक मिनट के लिए (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> तक)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d मिनट के लिए (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> तक)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"एक घंटे के लिए (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> तक)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d घंटो के लिए (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> तक)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"एक मिनट के लिए"</item>
- <item quantity="other" msgid="6924190729213550991">"%d मिनट के लिए"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"एक घंटे के लिए"</item>
- <item quantity="other" msgid="5408537517529822157">"%d घंटे के लिए"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d मिनट के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
+ <item quantity="other">%1$d मिनट के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d घंटे के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
+ <item quantity="other">%1$d घंटे के लिए (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> तक)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d मिनट के लिए</item>
+ <item quantity="other">%d मिनट के लिए</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d घंटे के लिए</item>
+ <item quantity="other">%d घंटे के लिए</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> तक"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित समय तक"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"संक्षिप्त करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index af4a687..fbb9160 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -61,10 +61,11 @@
<string name="needPuk" msgid="919668385956251611">"Vaša je SIM kartica zaključana PUK-om. Unesite PUK kôd da biste je otključali."</string>
<string name="needPuk2" msgid="4526033371987193070">"Unesite PUK2 da biste odblokirali SIM karticu."</string>
<string name="enablePin" msgid="209412020907207950">"Neuspješno; omogući zaključavanje SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Imate još <xliff:g id="NUMBER">%d</xliff:g> pokušaj prije zaključavanja SIM kartice."</item>
- <item quantity="other" msgid="7530597808358774740">"Imate još nekoliko preostalih pokušaja (<xliff:g id="NUMBER">%d</xliff:g>) prije zaključavanja SIM kartice."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj prije zaključavanja SIM kartice.</item>
+ <item quantity="few">Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja prije zaključavanja SIM kartice.</item>
+ <item quantity="other">Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja prije zaključavanja SIM kartice.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID dolaznog pozivatelja"</string>
@@ -1131,73 +1132,13 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Usluga <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> želi omogućiti značajku Istraživanje dodirom. Kad je značajka Istraživanje dodirom uključena, možete čuti ili vidjeti opise onoga što je pod vašim prstom ili izvršiti pokrete za interakciju s telefonom."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Prije 1 mjesec"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Prije 1 mjesec"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Prije 1 sekundu"</item>
- <item quantity="other" msgid="3903706804349556379">"prije <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"prije 1 minutu"</item>
- <item quantity="other" msgid="2176942008915455116">"Prije <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Prije 1 sata"</item>
- <item quantity="other" msgid="2467273239587587569">"Prije <xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Posljednjih <xliff:g id="COUNT_1">%d</xliff:g> dan</item>
+ <item quantity="few">Posljednja <xliff:g id="COUNT_1">%d</xliff:g> dana</item>
+ <item quantity="other">Posljednjih <xliff:g id="COUNT_1">%d</xliff:g> dana</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Prošli mjesec"</string>
<string name="older" msgid="5211975022815554840">"Starije"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"jučer"</item>
- <item quantity="other" msgid="2479586466153314633">"Prije <xliff:g id="COUNT">%d</xliff:g> dana"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"za 1 sekundu"</item>
- <item quantity="other" msgid="1241926116443974687">"za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"za 1 minutu"</item>
- <item quantity="other" msgid="3330713936399448749">"za sljedeći broj minuta: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"za 1 sat"</item>
- <item quantity="other" msgid="547290677353727389">"za <xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"sutra"</item>
- <item quantity="other" msgid="5109449375100953247">"za sljedeći broj dana: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Prije 1 s"</item>
- <item quantity="other" msgid="3699169366650930415">"Prije <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Prije 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"Prije <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Prije 1 sat"</item>
- <item quantity="other" msgid="6889970745748538901">"Prije <xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"jučer"</item>
- <item quantity="other" msgid="3453342639616481191">"Prije <xliff:g id="COUNT">%d</xliff:g> dana"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"za 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"za 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"za <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"za 1 sat"</item>
- <item quantity="other" msgid="3705373766798013406">"za sljedeći broj sati: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"sutra"</item>
- <item quantity="other" msgid="2973062968038355991">"za sljedeći broj dana: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"dana <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"u <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>."</string>
@@ -1213,18 +1154,21 @@
<string name="weeks" msgid="6509623834583944518">"tjedna"</string>
<string name="year" msgid="4001118221013892076">"godina"</string>
<string name="years" msgid="6881577717993213522">"godina"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 s"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 min"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 sat"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekunda</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekunde</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekundi</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minuta</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuta</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sat</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sata</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sati</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problem s videozapisom"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ovaj videozapis nije valjan za streaming na ovaj uređaj."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ovaj videozapis nije moguće reproducirati."</string>
@@ -1333,14 +1277,16 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nijedan"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvona"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nepoznata melodija zvona"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Dostupna je Wi-Fi mreža"</item>
- <item quantity="other" msgid="4192424489168397386">"Dostupne su Wi-Fi mreže"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Omogućavanje otvaranja Wi-Fi mreže"</item>
- <item quantity="other" msgid="7915895323644292768">"Omogućavanje otvaranja Wi-Fi mreža"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Dostupne su Wi-Fi mreže</item>
+ <item quantity="few">Dostupne su Wi-Fi mreže</item>
+ <item quantity="other">Dostupne su Wi-Fi mreže</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Dostupne su otvorene Wi-Fi mreže</item>
+ <item quantity="few">Dostupne su otvorene Wi-Fi mreže</item>
+ <item quantity="other">Dostupne su otvorene Wi-Fi mreže</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Prijavite se na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Prijavite se na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1362,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"U redu"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Spojen kao medijski uređaj"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Spojen kao fotoaparat"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Povezan kao MIDI uređaj"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Spojen kao instalacijski program"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Spojen na USB pribor"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Dodirnite za ostale opcije USB uređaja"</string>
@@ -1531,10 +1478,11 @@
<string name="skip_button_label" msgid="1275362299471631819">"Preskoči"</string>
<string name="no_matches" msgid="8129421908915840737">"Nema rezultata"</string>
<string name="find_on_page" msgid="1946799233822820384">"Pronađi na stranici"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 podudaranje"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Gotovo"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Isključivanje USB pohrane..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Isključivanje SD kartice..."</string>
@@ -1820,10 +1768,11 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Izradite PIN za izmjenu ograničenja"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-ovi se ne podudaraju. Pokušajte ponovo."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN je prekratak. Mora imati barem 4 znamenke."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Ponovite za 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Ponovite za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundu</item>
+ <item quantity="few">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekunde</item>
+ <item quantity="other">Pokušajte ponovo za <xliff:g id="COUNT">%d</xliff:g> sekundi</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Pokušajte ponovo kasnije"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Prijeđite prstom s vrha prema dolje za izlaz iz cijelog zaslona."</string>
<string name="done_label" msgid="2093726099505892398">"Gotovo"</string>
@@ -1849,22 +1798,26 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Da bi se produljilo trajanje baterije, ušteda baterije smanjuje rad uređaja i ograničava vibraciju, usluge lokacije i većinu pozadinskih podataka. Aplikacije za e-poštu, slanje poruka i druge aplikacije koje se oslanjaju na sinkronizaciju možda se neće ažurirati ako ih ne otvorite.\n\nUšteda baterije isključuje se automatski dok se uređaj puni."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dok razdoblje zastoja ne završi u <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Do završetka prekida rada"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Jednu minutu (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d min (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Jedan sat (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d h (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Jednu minutu"</item>
- <item quantity="other" msgid="6924190729213550991">"%d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Jedan sat"</item>
- <item quantity="other" msgid="5408537517529822157">"%d h"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d minutu (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d minute (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d minuta (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d sat (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d sata (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d sati (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d minutu</item>
+ <item quantity="few">%d minute</item>
+ <item quantity="other">%d minuta</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d sat</item>
+ <item quantity="few">%d sata</item>
+ <item quantity="other">%d sati</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Neodređeno"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Sažmi"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 2a993cd..5a929bd 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"A SIM kártya le van zárva a PUK kóddal. A feloldáshoz adja meg a PUK kódot."</string>
<string name="needPuk2" msgid="4526033371987193070">"A SIM kártya feloldásához adja meg a PUK2 kódot."</string>
<string name="enablePin" msgid="209412020907207950">"Sikertelen, engedélyezze a SIM-/RUIM-zárolást."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van, mielőtt zároljuk a SIM kártyát."</item>
- <item quantity="other" msgid="7530597808358774740">"Még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van, mielőtt zároljuk a SIM kártyát."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Még <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozása van a SIM kártya zárolásáig.</item>
+ <item quantity="one">Még <xliff:g id="NUMBER_0">%d</xliff:g> próbálkozása van a SIM kártya zárolásáig.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Beérkező hívóazonosító"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> aktiválni szeretné a Felfedezés érintéssel funkciót. Amikor be van kapcsolva a Felfedezés érintéssel, akkor hallhatja vagy láthatja annak leírását, ami az ujja alatt van, illetve végrehajthat kézmozdulatokat a telefon kezeléséhez."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 hónapja"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Több mint 1 hónapja"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 másodperce"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> másodperce"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 perce"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> perce"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 órája"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> órája"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">A legutóbbi <xliff:g id="COUNT_1">%d</xliff:g> nap</item>
+ <item quantity="one">A legutóbbi <xliff:g id="COUNT_0">%d</xliff:g> nap</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Múlt hónapban"</string>
<string name="older" msgid="5211975022815554840">"Régebbi"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"tegnap"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> napja"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 másodperc múlva"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> másodperc múlva"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 perc múlva"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> perc múlva"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 óra múlva"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> óra múlva"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"holnap"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> nap múlva"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 másodperce"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> másodperce"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 perce"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> perce"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 órája"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> órája"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"tegnap"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> napja"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 másodperc múlva"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> másodperc múlva"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 perc múlva"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> perc múlva"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 óra múlva"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> óra múlva"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"holnap"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> nap múlva"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"e napon: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"év: <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"hét"</string>
<string name="year" msgid="4001118221013892076">"év"</string>
<string name="years" msgid="6881577717993213522">"év"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 másodperc"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> másodperc"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 perc"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> perc"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 óra"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> óra"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> másodperc</item>
+ <item quantity="one">1 másodperc</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> perc</item>
+ <item quantity="one">1 perc</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> óra</item>
+ <item quantity="one">1 óra</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoprobléma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ezt a videót nem lehet megjeleníteni ezen az eszközön."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nem lehet lejátszani ezt a videót."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Egyik sem"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Csengőhangok"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Ismeretlen csengőhang"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi hálózat elérhető"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi hálózatok elérhetők"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Nyílt Wi-Fi hálózat elérhető"</item>
- <item quantity="other" msgid="7915895323644292768">"Nyílt Wi-Fi hálózatok elérhetők"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi hálózatok érhetők el</item>
+ <item quantity="one">Van elérhető Wi-Fi hálózat</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Nyílt Wi-Fi hálózatok érhetők el</item>
+ <item quantity="one">Nyílt Wi-Fi hálózat érhető el</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Bejelentkezés Wi-Fi hálózatba"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Bejelentkezés a hálózatba"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Csatlakoztatva médiaeszközként"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Csatlakoztatva kameraként"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Csatlakoztatva MIDI-eszközként"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Csatlakoztatva telepítőként"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Csatlakoztatva egy USB-kiegészítőhöz"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Érintse meg a további USB-opciókért."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Kihagyás"</string>
<string name="no_matches" msgid="8129421908915840737">"Nincs találat"</string>
<string name="find_on_page" msgid="1946799233822820384">"Keresés az oldalon"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 találat"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>/<xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 találat</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Kész"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Az USB-tár leválasztása..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD-kártya leválasztása..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"PIN kód létrehozása a korlátozások módosításához"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"A PIN kódok nem egyeznek. Próbálja újra."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"A PIN kód túl rövid. Legalább 4 számjegyből kell állnia."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Próbálja újra 1 másodperc múlva"</item>
- <item quantity="other" msgid="4730868920742952817">"Próbálja újra <xliff:g id="COUNT">%d</xliff:g> másodperc múlva"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Próbálja újra <xliff:g id="COUNT">%d</xliff:g> másodperc múlva</item>
+ <item quantity="one">Próbálja újra 1 másodperc múlva</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Próbálkozzon később"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"A teljes képernyős nézetből való kilépéshez húzza ujját a képernyő tetejétől lefelé."</string>
<string name="done_label" msgid="2093726099505892398">"Kész"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Az akkumulátoridő növelése érdekében az energiatakarékos mód csökkenti az eszköz teljesítményét, és korlátozza a rezgést, a helyszolgáltatásokat, valamint a legtöbb háttéradatot is. Előfordulhat, hogy azok az e-mail-, üzenetküldő és egyéb alkalmazások, amelyek szinkronizálására számít, csak akkor frissítenek, ha megnyitja azokat.\n\nAz energiatakarékos mód automatikusan kikapcsol, ha eszköze töltőn van."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Amíg az állásidő véget nem ér ekkor: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Amíg az inaktivitás véget nem ér"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Egy percre (eddig: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d percre (eddig: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Egy órára (eddig: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d órára (eddig: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Egy percen át"</item>
- <item quantity="other" msgid="6924190729213550991">"%d percen át"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Egy órán át"</item>
- <item quantity="other" msgid="5408537517529822157">"%d órán át"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d percen át (eddig: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Egy percen át (eddig: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d órán át (eddig: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Egy órán át (eddig: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d percen át</item>
+ <item quantity="one">Egy percen át</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d órán át</item>
+ <item quantity="one">Egy órán át</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Határozatlan ideig"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Összecsukás"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index c48571e..a6f9496 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -21,7 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="byteShort" msgid="8340973892742019101">"Բ"</string>
- <string name="kilobyteShort" msgid="5973789783504771878">"Կբ"</string>
+ <string name="kilobyteShort" msgid="5973789783504771878">"ԿԲ"</string>
<string name="megabyteShort" msgid="6355851576770428922">"ՄԲ"</string>
<string name="gigabyteShort" msgid="3259882455212193214">"ԳԲ"</string>
<string name="terabyteShort" msgid="231613018159186962">"Տբ"</string>
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Ձեր SIM քարտը PUK-ով կողպված է: Մուտքագրեք PUK կոդը այն ապակողպելու համար:"</string>
<string name="needPuk2" msgid="4526033371987193070">"Մուտքագրեք PUK2-ը` SIM քարտն արգելաբացելու համար:"</string>
<string name="enablePin" msgid="209412020907207950">"Ձախողվեց: Միացրեք SIM/RUIM կողպումը:"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ՝ մինչև SIM-ի արգելափակումը:"</item>
- <item quantity="other" msgid="7530597808358774740">"Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ՝ մինչև SIM-ի արգելափակումը:"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն արգելափակվելու է:</item>
+ <item quantity="other">Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն արգելափակվելու է:</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Մուտքային զանգողի ID"</string>
@@ -1058,7 +1058,7 @@
<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">"JavaScript"</string>
- <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Հաստատել կողմնորոշումը"</string>
+ <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Գործողության հաստատում"</string>
<string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"Լքել այս էջը"</string>
<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>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 վայրկյան առաջ"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> վայրկյան առաջ"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 րոպե առաջ"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> րոպե առաջ"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ժամ առաջ"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ժամ առաջ"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Վերջին <xliff:g id="COUNT_1">%d</xliff:g> օրում</item>
+ <item quantity="other">Վերջին <xliff:g id="COUNT_1">%d</xliff:g> օրում</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Անցյալ ամիս"</string>
<string name="older" msgid="5211975022815554840">"Ավելի հին"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"երեկ"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> օր առաջ"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 վայրկյանից"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> վայրկյանից"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 րոպեից"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> րոպեից"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 ժամից"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> ժամից"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"վաղը"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> օրից"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 վրկ առաջ"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> վրկ. առաջ"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 րոպե առաջ"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> րոպե առաջ"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ժամ առաջ"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ժամ առաջ"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"երեկ"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> օր առաջ"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 վրկ-ից"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> վրկ-ից"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 րոպեից"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> րոպեից"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 ժամից"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> ժամից"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"վաղը"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> օրից"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>-ին"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ժամը <xliff:g id="TIME">%s</xliff:g>-ին"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> թվականին"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"շաբաթ"</string>
<string name="year" msgid="4001118221013892076">"տարի"</string>
<string name="years" msgid="6881577717993213522">"տարի"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 վայրկյան"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> վայրկյան"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 րոպե"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> րոպե"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ժամ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ժամ"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> վայրկյան</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> վայրկյան</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> րոպե</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> րոպե</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ժամ</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ոչ մեկը"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Զանգերանգներ"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Անհայտ զանգերանգ"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi ցանցը հասանելի է"</item>
- <item quantity="other" msgid="4192424489168397386">"հասանելի են Wi-Fi ցանցեր"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Բաց Wi-Fi ցանցը հասանելի է"</item>
- <item quantity="other" msgid="7915895323644292768">"Հասանելի են բաց Wi-Fi ցանցեր"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Հասանելի են Wi-Fi ցանցեր</item>
+ <item quantity="other">Հասանելի են Wi-Fi ցանցեր</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
+ <item quantity="other">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Մուտք գործեք Wi-Fi ցանց"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Մուտք գործել ցանց"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Լավ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Կապակցված է որպես մեդիա սարք"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Միացված է որպես ֆոտոխցիկ"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Կապակցված է որպես MIDI սարք"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Միացված է որպես տեղադրիչ"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Կապակցված է USB լրասարքի"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Հպեք` այլ USB ընտրանքների համար:"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 համընկնում"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>-ից <xliff:g id="INDEX">%d</xliff:g>-ը"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g>՝ <xliff:g id="TOTAL">%d</xliff:g>-ից</item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>՝ <xliff:g id="TOTAL">%d</xliff:g>-ից</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Կատարված է"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Անջատվում է USB կրիչը..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Անջատում է SD քարտը..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN-ը չափազանց կարճ է: Պետք է ունենա առնվազն 4 թվանիշ:"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Կրկին փորձեք 1 վայրկյանից"</item>
- <item quantity="other" msgid="4730868920742952817">"Կրկին փորձեք <xliff:g id="COUNT">%d</xliff:g> վայրկյանից"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Կրկին փորձեք <xliff:g id="COUNT">%d</xliff:g> վայրկյանից</item>
+ <item quantity="other">Կրկին փորձեք <xliff:g id="COUNT">%d</xliff:g> վայրկյանից</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Կրկին փորձեք մի փոքր ուշ"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Սահահարվածեք վերից վար՝ ամբողջական էկրանից դուրս գալու համար:"</string>
<string name="done_label" msgid="2093726099505892398">"Պատրաստ է"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Մարտկոցի աշխատանքի ժամկետը երկարացնելու նպատակով, մարտկոցի էներգիայի խնայման գործառույթը սահմանափակում է սարքի աշխատանքը, թրթռոցը, տեղադրության ծառայությունները և հետնաշերտում աշխատող շատ գործընթացներ: Էլփոստը, հաղորդագրությունների փոխանակումը և տվյալների համաժամեցումից կախված այլ հավելվածները կարող են չթարմացվել, եթե դուք դրանք չգործարկեք:\n\nԵրբ ձեր սարքը լիցքավորվում է, մարտկոցի էներգիայի խնայման գործառույթն ինքնաշխատորեն անջատվում է:"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Մինչև ձեր ժամանակն ավարտվի ժամը <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Մինչև անգործունության ժամանակն ավարտվի"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Մեկ րոպե (մինչև <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d րոպե (մինչև <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Մեկ ժամ (մինչև <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d ժամ (մինչև <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item>
- <item quantity="other" msgid="6924190729213550991">"%d րոպե"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Մեկ ժամ"</item>
- <item quantity="other" msgid="5408537517529822157">"%d ժամ"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d րոպե (մինչև <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d րոպե (մինչև <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d ժամ (մինչև <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d ժամ (մինչև <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d րոպե</item>
+ <item quantity="other">%d րոպե</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d ժամ</item>
+ <item quantity="other">%d ժամ</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Մինչև <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Անորոշ ժամանակով"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Թաքցնել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 3eba049..4dc7d62 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Kartu SIM Anda dikunci PUK. Ketikkan kode PUK untuk membukanya."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ketikkan PUK2 untuk membuka kartu SIM"</string>
<string name="enablePin" msgid="209412020907207950">"Gagal, aktifkan Kunci SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan sebelum SIM terkunci."</item>
- <item quantity="other" msgid="7530597808358774740">"Sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan sebelum SIM terkunci."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Sisa <xliff:g id="NUMBER_1">%d</xliff:g> percobaan sebelum SIM terkunci.</item>
+ <item quantity="one">Sisa <xliff:g id="NUMBER_0">%d</xliff:g> percobaan sebelum SIM terkunci.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Nomor Penelepon Masuk"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mengaktifkan Menjelajah dengan Sentuhan. Saat Menjelajah dengan Sentuhan diaktifkan, Anda dapat mendengar atau melihat deskripsi dari apa yang ada di bawah jari Anda atau melakukan gerakan untuk berinteraksi dengan ponsel."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 bulan yang lalu"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Sebelum 1 bulan yang lalu"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 detik lalu"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> detik yang lalu"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 menit yang lalu"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> menit yang lalu"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 jam yang lalu"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> <xliff:g id="COUNT_1">%d</xliff:g> hari terakhir</item>
+ <item quantity="one"> <xliff:g id="COUNT_0">%d</xliff:g> hari terakhir</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Bulan lalu"</string>
<string name="older" msgid="5211975022815554840">"Lawas"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"kemarin"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> hari yang lalu"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"dalam 1 detik"</item>
- <item quantity="other" msgid="1241926116443974687">"dalam <xliff:g id="COUNT">%d</xliff:g> detik"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"dalam 1 menit"</item>
- <item quantity="other" msgid="3330713936399448749">"dalam <xliff:g id="COUNT">%d</xliff:g> menit"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"dalam 1 jam"</item>
- <item quantity="other" msgid="547290677353727389">"dalam <xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"besok"</item>
- <item quantity="other" msgid="5109449375100953247">"dalam <xliff:g id="COUNT">%d</xliff:g> hari"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 detik yang lalu"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> detik yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 menit yang lalu"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> menit yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 jam yang lalu"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"kemarin"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> hari yang lalu"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"dalam 1 detik"</item>
- <item quantity="other" msgid="5495880108825805108">"dalam <xliff:g id="COUNT">%d</xliff:g> detik"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"dalam 1 menit"</item>
- <item quantity="other" msgid="4216113292706568726">"dalam <xliff:g id="COUNT">%d</xliff:g> menit"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"dalam 1 jam"</item>
- <item quantity="other" msgid="3705373766798013406">"dalam <xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"besok"</item>
- <item quantity="other" msgid="2973062968038355991">"dalam <xliff:g id="COUNT">%d</xliff:g> hari"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"pada <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"dalam <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"minggu"</string>
<string name="year" msgid="4001118221013892076">"tahun"</string>
<string name="years" msgid="6881577717993213522">"tahun"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 detik"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> detik"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 menit"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> menit"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> detik</item>
+ <item quantity="one">1 detik</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> menit</item>
+ <item quantity="one">1 menit</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> jam</item>
+ <item quantity="one">1 jam</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video ini tidak valid untuk pengaliran ke perangkat ini."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat memutar video ini."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Tidak Ada"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak dikenal"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Jaringan Wi-Fi tersedia"</item>
- <item quantity="other" msgid="4192424489168397386">"Jaringan Wi-Fi"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Jaringan Wi-Fi terbuka tersedia"</item>
- <item quantity="other" msgid="7915895323644292768">"Jaringan Wi-Fi terbuka tersedia"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Jaringan Wi-Fi tersedia</item>
+ <item quantity="one">Jaringan Wi-Fi tersedia</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Jaringan Wi-Fi terbuka tersedia</item>
+ <item quantity="one">Jaringan Wi-Fi terbuka tersedia</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Masuk ke jaringan Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Masuk ke jaringan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Oke"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tersambung sebagai perangkat media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tersambung sebagai kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Terhubung sebagai perangkat MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tersambung sebagai pemasang"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Tersambung ke aksesori USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Sentuh untuk opsi USB lainnya."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Lewati"</string>
<string name="no_matches" msgid="8129421908915840737">"Tidak ada kecocokan"</string>
<string name="find_on_page" msgid="1946799233822820384">"Temukan pada laman"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 kecocokan"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> dari <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> dari <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 kecocokan</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Selesai"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Melepas penyimpanan USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Melepas kartu SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Buat PIN untuk mengubah batasan"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN tidak cocok. Coba lagi."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN terlalu pendek. Minimal 4 digit."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Coba 1 dtk lagi"</item>
- <item quantity="other" msgid="4730868920742952817">"Coba <xliff:g id="COUNT">%d</xliff:g> detik lagi"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Coba <xliff:g id="COUNT">%d</xliff:g> detik lagi</item>
+ <item quantity="one">Coba 1 detik lagi</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Coba lagi nanti"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Gesek dari atas ke bawah untuk keluar dari layar penuh."</string>
<string name="done_label" msgid="2093726099505892398">"Selesai"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Untuk membantu meningkatkan masa pakai baterai, penghemat baterai mengurangi kinerja perangkat dan membatasi getaran, layanan lokasi, dan kebanyakan data latar belakang. Email, perpesanan, dan aplikasi lain yang mengandalkan sinkronisasi mungkin tidak diperbarui kecuali jika dibuka.\n\nPenghemat baterai otomatis nonaktif jika perangkat diisi dayanya."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hingga waktu perbaikan Anda berakhir pukul <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Hingga waktu non-operasional berakhir"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Selama semenit (hingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Selama %1$d menit (hingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Selama sejam (hingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Selama %1$d jam (hingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Selama satu menit"</item>
- <item quantity="other" msgid="6924190729213550991">"Selama %d menit"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
- <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Selama %1$d menit (hingga <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Selama satu menit (hingga <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Selama %1$d jam (hingga <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Selama satu jam (hingga <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Selama %d menit</item>
+ <item quantity="one">Selama satu menit</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Selama %d jam</item>
+ <item quantity="one">Selama satu jam</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Tidak ditentukan"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Ciutkan"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 690d6e54..6f8bd07 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM-kortið er PUK-læst. Sláðu inn PUK-númerið til að taka það úr lás."</string>
<string name="needPuk2" msgid="4526033371987193070">"Sláðu inn PUK2-númer að taka SIM-kortið úr lás."</string>
<string name="enablePin" msgid="209412020907207950">"Tókst ekki. Kveiktu á SIM-/RUIM-lás."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraun eftir áður en SIM-kortinu verður læst."</item>
- <item quantity="other" msgid="7530597808358774740">"Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraunir eftir áður en SIM-kortinu verður læst."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraun eftir áður en SIM-kortinu verður læst.</item>
+ <item quantity="other">Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraunir eftir áður en SIM-kortinu verður læst.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Númerabirting innhringinga"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill kveikja á snertikönnun. Þegar kveikt er á snertikönnun geturðu heyrt eða séð lýsingu á því sem er á skjánum undir fingrinum hverju sinni eða notað bendingar til að stjórna símanum."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Fyrir mánuði"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Fyrir meira en mánuði"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"fyrir sekúndu"</item>
- <item quantity="other" msgid="3903706804349556379">"fyrir <xliff:g id="COUNT">%d</xliff:g> sekúndum"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"fyrir mínútu"</item>
- <item quantity="other" msgid="2176942008915455116">"fyrir <xliff:g id="COUNT">%d</xliff:g> mínútum"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"fyrir klukkustund"</item>
- <item quantity="other" msgid="2467273239587587569">"fyrir <xliff:g id="COUNT">%d</xliff:g> klukkustundum"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Undanfarinn <xliff:g id="COUNT_1">%d</xliff:g> dag</item>
+ <item quantity="other">Undanfarna <xliff:g id="COUNT_1">%d</xliff:g> daga</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Í síðasta mánuði"</string>
<string name="older" msgid="5211975022815554840">"Eldra"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"í gær"</item>
- <item quantity="other" msgid="2479586466153314633">"fyrir <xliff:g id="COUNT">%d</xliff:g> dögum"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"eftir sekúndu"</item>
- <item quantity="other" msgid="1241926116443974687">"eftir <xliff:g id="COUNT">%d</xliff:g> sekúndur"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"eftir mínútu"</item>
- <item quantity="other" msgid="3330713936399448749">"eftir <xliff:g id="COUNT">%d</xliff:g> mínútur"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"eftir klukkustund"</item>
- <item quantity="other" msgid="547290677353727389">"eftir <xliff:g id="COUNT">%d</xliff:g> klukkustundir"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"á morgun"</item>
- <item quantity="other" msgid="5109449375100953247">"eftir <xliff:g id="COUNT">%d</xliff:g> daga"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"fyrir sekúndu"</item>
- <item quantity="other" msgid="3699169366650930415">"fyrir <xliff:g id="COUNT">%d</xliff:g> sekúndum"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"fyrir mínútu"</item>
- <item quantity="other" msgid="851164968597150710">"fyrir <xliff:g id="COUNT">%d</xliff:g> mínútum"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"fyrir klukkustund"</item>
- <item quantity="other" msgid="6889970745748538901">"fyrir <xliff:g id="COUNT">%d</xliff:g> klukkustundum"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"í gær"</item>
- <item quantity="other" msgid="3453342639616481191">"fyrir <xliff:g id="COUNT">%d</xliff:g> dögum"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"eftir sekúndu"</item>
- <item quantity="other" msgid="5495880108825805108">"eftir <xliff:g id="COUNT">%d</xliff:g> sekúndur"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"eftir mínútu"</item>
- <item quantity="other" msgid="4216113292706568726">"eftir <xliff:g id="COUNT">%d</xliff:g> mínútur"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"eftir klukkustund"</item>
- <item quantity="other" msgid="3705373766798013406">"eftir <xliff:g id="COUNT">%d</xliff:g> klukkustundir"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"á morgun"</item>
- <item quantity="other" msgid="2973062968038355991">"eftir <xliff:g id="COUNT">%d</xliff:g> daga"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"vikur"</string>
<string name="year" msgid="4001118221013892076">"ár"</string>
<string name="years" msgid="6881577717993213522">"ár"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekúnda"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekúndur"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 mínúta"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> mínútur"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 klukkustund"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> klukkustundir"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekúnda</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekúndur</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> mínúta</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> mínútur</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> klukkustund</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> klukkustundir</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Vandamál með myndskeið"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Þetta myndskeið er ekki gjaldgengt fyrir straumspilun í þessu tæki."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ekki er hægt að spila þetta myndskeið."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Enginn"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Hringitónar"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Óþekktur hringitónn"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi net í boði"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi net í boði"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Opið Wi-Fi net í boði"</item>
- <item quantity="other" msgid="7915895323644292768">"Opin Wi-Fi net í boði"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Wi-Fi net í boði</item>
+ <item quantity="other">Wi-Fi net í boði</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Opin Wi-Fi net í boði</item>
+ <item quantity="other">Opin Wi-Fi net í boði</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Skrá inn á Wi-Fi net"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Skrá inn á net"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Í lagi"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tengt sem geymslumiðill"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tengt sem myndavél"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Tengt sem MIDI-tæki"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tengt sem uppsetningarforrit"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Tengt við USB-aukabúnað"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Snertu til að sjá aðra USB-valkosti."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Sleppa"</string>
<string name="no_matches" msgid="8129421908915840737">"Engar samsvaranir"</string>
<string name="find_on_page" msgid="1946799233822820384">"Finna á síðu"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"Ein samsvörun"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Lokið"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Aftengir USB-geymslu…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Aftengir SD-kort…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Búðu til PIN-númer til að breyta takmörkunum"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-númerin stemma ekki. Reyndu aftur."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN-númerið er of stutt. Það verður að vera a.m.k. 4 tölustafir."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Reyndu aftur eftir sekúndu"</item>
- <item quantity="other" msgid="4730868920742952817">"Reyndu aftur eftir <xliff:g id="COUNT">%d</xliff:g> sekúndur"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Reyndu aftur eftir <xliff:g id="COUNT">%d</xliff:g> sekúndu</item>
+ <item quantity="other">Reyndu aftur eftir <xliff:g id="COUNT">%d</xliff:g> sekúndur</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Reyndu aftur síðar"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Strjúktu niður frá efri brún til að hætta að nota allan skjáinn."</string>
<string name="done_label" msgid="2093726099505892398">"Lokið"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Til að auka endingu rafhlöðunnar mun orkusparnaður draga úr afköstum tækisins og takmarka titring, staðsetningarþjónustu og megnið af bakgrunnsgögnum. Ekki er víst að tölvupóstur, skilaboð og önnur forrit sem reiða sig á samstillingu uppfærist nema þú opnir þau.\n\nSjálfkrafa er slökkt á orkusparnaði þegar tækið er í hleðslu."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Þangað til niðritíma lýkur, <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Þar til niðritíma lýkur"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Í eina mínútu (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Í %1$d mín. (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Í eina klukkustund (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Í %1$d klst. (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Í eina mínútu"</item>
- <item quantity="other" msgid="6924190729213550991">"Í %d mínútur"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Í eina klukkustund"</item>
- <item quantity="other" msgid="5408537517529822157">"Í %d klukkustundir"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Í %1$d mínútu (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Í %1$d mínútur (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Í %1$d klukkustund (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Í %1$d klukkustundir (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Í %d mínútu</item>
+ <item quantity="other">Í %d mínútur</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Í %d klukkustund</item>
+ <item quantity="other">Í %d klukkustundir</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Án tímatakmarkana"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Minnka"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bea0c13..c6b18e8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"La SIM è bloccata tramite PUK. Digita il codice PUK per sbloccarla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Digita il PUK2 per sbloccare la SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Operazione non riuscita; attiva blocco SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativo a disposizione prima che la SIM venga bloccata."</item>
- <item quantity="other" msgid="7530597808358774740">"Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativi a disposizione prima che la SIM venga bloccata."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM venga bloccata.</item>
+ <item quantity="one">Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM venga bloccata.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID chiamante in entrata"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vuole attivare la funzione Esplora al tocco. Quando la funzione Esplora al tocco è attiva, puoi ascoltare o visualizzare le descrizioni di ciò che stai toccando oppure interagire con il telefono tramite gesti."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 mese fa"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Oltre 1 mese fa"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 secondo fa"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> secondi fa"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuto fa"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minuti fa"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ora fa"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ore fa"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Ultimi <xliff:g id="COUNT_1">%d</xliff:g> giorni</item>
+ <item quantity="one">Ultimo giorno (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Ultimo mese"</string>
<string name="older" msgid="5211975022815554840">"Precedente"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ieri"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> giorni fa"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"tra 1 secondo"</item>
- <item quantity="other" msgid="1241926116443974687">"tra <xliff:g id="COUNT">%d</xliff:g> secondi"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"tra 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"tra <xliff:g id="COUNT">%d</xliff:g> minuti"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"tra 1 ora"</item>
- <item quantity="other" msgid="547290677353727389">"tra <xliff:g id="COUNT">%d</xliff:g> ore"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"domani"</item>
- <item quantity="other" msgid="5109449375100953247">"tra <xliff:g id="COUNT">%d</xliff:g> giorni"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 sec fa"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> sec fa"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min fa"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> min fa"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ora fa"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ore fa"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ieri"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> giorni fa"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"tra 1 sec"</item>
- <item quantity="other" msgid="5495880108825805108">"tra <xliff:g id="COUNT">%d</xliff:g> sec"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"tra 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"tra <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"tra 1 ora"</item>
- <item quantity="other" msgid="3705373766798013406">"tra <xliff:g id="COUNT">%d</xliff:g> ore"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"domani"</item>
- <item quantity="other" msgid="2973062968038355991">"tra <xliff:g id="COUNT">%d</xliff:g> giorni"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"in data <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"alle ore <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"nel <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"settimane"</string>
<string name="year" msgid="4001118221013892076">"anno"</string>
<string name="years" msgid="6881577717993213522">"anni"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 secondo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> secondi"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuti"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ore"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> secondi</item>
+ <item quantity="one">1 secondo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuti</item>
+ <item quantity="one">1 minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ore</item>
+ <item quantity="one">1 ora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemi video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Questo video non è valido per lo streaming su questo dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Impossibile riprodurre il video."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nessuna"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Suonerie"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Suoneria sconosciuta"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Rete Wi-Fi disponibile"</item>
- <item quantity="other" msgid="4192424489168397386">"Reti Wi-Fi disponibili"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Rete Wi-Fi aperta disponibile"</item>
- <item quantity="other" msgid="7915895323644292768">"Reti Wi-Fi aperte disponibili"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Reti Wi-Fi disponibili</item>
+ <item quantity="one">Rete Wi-Fi disponibile</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Apri reti Wi-Fi disponibili</item>
+ <item quantity="one">Apri rete Wi-Fi disponibile</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Accedi a rete Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Accedi alla rete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Collegato come dispositivo multimediale"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Collegato come fotocamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Connesso come un dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Collegato come installer"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Collegato a un accessorio USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Tocca per altre opzioni USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ignora"</string>
<string name="no_matches" msgid="8129421908915840737">"Nessuna corrispondenza"</string>
<string name="find_on_page" msgid="1946799233822820384">"Trova nella pagina"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 corrispondenza"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> di <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> di <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 partita</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Fine"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Smontaggio dell\'archivio USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Smontaggio scheda SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crea un PIN per la modifica delle limitazioni"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"I PIN non corrispondono. Riprova."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Il PIN è troppo corto. Deve avere almeno quattro cifre."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Riprova fra 1 s."</item>
- <item quantity="other" msgid="4730868920742952817">"Riprova tra <xliff:g id="COUNT">%d</xliff:g> s."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Riprova tra <xliff:g id="COUNT">%d</xliff:g> secondi</item>
+ <item quantity="one">Riprova tra 1 secondo</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Riprova più tardi"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Scorri dall\'alto verso il basso per uscire dalla modalità schermo intero."</string>
<string name="done_label" msgid="2093726099505892398">"Fine"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Per aumentare la durata della batteria, la funzione di risparmio energetico riduce le prestazioni del dispositivo e limita vibrazione, servizi di localizzazione e la maggior parte dei dati in background. App di email, messaggi e altre app che si basano sulla sincronizzazione potrebbero essere aggiornate soltanto all\'apertura.\n\nLa funzione di risparmio energetico viene disattivata automaticamente quando il dispositivo è in carica."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Fino al termine del periodo di inattività previsto per le <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Fino al termine del periodo di inattività"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Per un minuto (fino alle ore <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Per un\'ora (fino alle ore <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Per %1$d ore (fino alle ore <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Per un minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Per %d minuti"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Per un\'ora"</item>
- <item quantity="other" msgid="5408537517529822157">"Per %d ore"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Per un minuto (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Per %1$d ore (fino alla ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Per un\'ora (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Per %d minuti</item>
+ <item quantity="one">Per un minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Per %d ore</item>
+ <item quantity="one">Per un\'ora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fino alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Sempre"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Comprimi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index edf5dd8..21ae52a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"כרטיס ה-SIM נעול באמצעות PUK. הקלד את קוד PUK כדי לבטל את נעילתו."</string>
<string name="needPuk2" msgid="4526033371987193070">"הקלד PUK2 כדי לבטל את חסימת כרטיס ה-SIM."</string>
<string name="enablePin" msgid="209412020907207950">"לא הצלחת. הפעל נעילת SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"נותר לך ניסיון <xliff:g id="NUMBER">%d</xliff:g> לפני נעילת כרטיס ה-SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"נותרו לך <xliff:g id="NUMBER">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="two">נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM.</item>
+ <item quantity="many">נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM.</item>
+ <item quantity="other">נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני נעילת כרטיס ה-SIM.</item>
+ <item quantity="one">נותר לך ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> לפני נעילת כרטיס ה-SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"זיהוי מתקשר של שיחה נכנסת"</string>
@@ -1131,73 +1133,14 @@
<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">"לפני חודש אחד"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"לפני חודש אחד"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"לפני שנייה אחת"</item>
- <item quantity="other" msgid="3903706804349556379">"לפני <xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"לפני דקה אחת"</item>
- <item quantity="other" msgid="2176942008915455116">"לפני <xliff:g id="COUNT">%d</xliff:g> דקות"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"לפני שעה"</item>
- <item quantity="other" msgid="2467273239587587569">"לפני <xliff:g id="COUNT">%d</xliff:g> שעות"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> הימים האחרונים</item>
+ <item quantity="one">יום <xliff:g id="COUNT_0">%d</xliff:g> אחרון</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"בחודש שעבר"</string>
<string name="older" msgid="5211975022815554840">"ישן יותר"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"אתמול"</item>
- <item quantity="other" msgid="2479586466153314633">"לפני <xliff:g id="COUNT">%d</xliff:g> ימים"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"בעוד שנייה אחת"</item>
- <item quantity="other" msgid="1241926116443974687">"תוך <xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"בעוד דקה אחת"</item>
- <item quantity="other" msgid="3330713936399448749">"תוך <xliff:g id="COUNT">%d</xliff:g> דקות"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"תוך שעה אחת"</item>
- <item quantity="other" msgid="547290677353727389">"תוך <xliff:g id="COUNT">%d</xliff:g> שעות"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"מחר"</item>
- <item quantity="other" msgid="5109449375100953247">"בעוד <xliff:g id="COUNT">%d</xliff:g> ימים"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"לפני שנייה אחת"</item>
- <item quantity="other" msgid="3699169366650930415">"לפני <xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"לפני דקה"</item>
- <item quantity="other" msgid="851164968597150710">"לפני <xliff:g id="COUNT">%d</xliff:g> דקות"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"לפני שעה"</item>
- <item quantity="other" msgid="6889970745748538901">"לפני <xliff:g id="COUNT">%d</xliff:g> שעות"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"אתמול"</item>
- <item quantity="other" msgid="3453342639616481191">"לפני <xliff:g id="COUNT">%d</xliff:g> ימים"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"תוך שנייה אחת"</item>
- <item quantity="other" msgid="5495880108825805108">"תוך <xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"תוך דקה אחת"</item>
- <item quantity="other" msgid="4216113292706568726">"תוך <xliff:g id="COUNT">%d</xliff:g> דקות"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"תוך שעה אחת"</item>
- <item quantity="other" msgid="3705373766798013406">"תוך <xliff:g id="COUNT">%d</xliff:g> שעות"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"מחר"</item>
- <item quantity="other" msgid="2973062968038355991">"בעוד <xliff:g id="COUNT">%d</xliff:g> ימים"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"בתאריך <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"בשנת <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"שבועות"</string>
<string name="year" msgid="4001118221013892076">"שנה"</string>
<string name="years" msgid="6881577717993213522">"שנים"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"שנייה אחת"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"דקה אחת"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> דקות"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"שעה אחת"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> שעות"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="one">שנייה אחת</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> דקות</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> דקות</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> דקות</item>
+ <item quantity="one">דקה אחת</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> שעות</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> שעות</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> שעות</item>
+ <item quantity="one">שעה אחת</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>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"רינגטון לא ידוע"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"רשת Wi-Fi זמינה"</item>
- <item quantity="other" msgid="4192424489168397386">"רשתות Wi-Fi זמינות"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"רשת Wi-Fi פתוחה זמינה"</item>
- <item quantity="other" msgid="7915895323644292768">"רשתות Wi-Fi פתוחות זמינות"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="two">יש רשתות Wi-Fi זמינות</item>
+ <item quantity="many">יש רשתות Wi-Fi זמינות</item>
+ <item quantity="other">יש רשתות Wi-Fi זמינות</item>
+ <item quantity="one">יש רשת Wi-Fi זמינה</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="two">יש רשתות Wi-Fi פתוחות וזמינות</item>
+ <item quantity="many">יש רשתות Wi-Fi פתוחות וזמינות</item>
+ <item quantity="other">יש רשתות Wi-Fi פתוחות וזמינות</item>
+ <item quantity="one">יש רשת Wi-Fi פתוחה וזמינה</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"כניסה לרשת Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"היכנס לרשת"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"אישור"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"מחובר כמכשיר מדיה"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"מחובר כמצלמה"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"מחובר כהתקן MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"מחובר כמתקין"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"מחובר לאביזר USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"גע לקבלת אפשרויות USB נוספות."</string>
@@ -1531,10 +1485,12 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"התאמה אחת"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> מתוך <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="two"><xliff:g id="INDEX">%d</xliff:g> מתוך <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> מתוך <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> מתוך <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">התאמה אחת</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"סיום"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"מבטל טעינה של אחסון USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"מבטל טעינה של כרטיס SD..."</string>
@@ -1820,10 +1776,12 @@
<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_too_short" msgid="8173982756265777792">"מספר ה-PIN קצר מדי. חייב להיות באורך 4 ספרות לפחות."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"נסה שוב בעוד שנייה"</item>
- <item quantity="other" msgid="4730868920742952817">"נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="two">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="many">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="other">נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות</item>
+ <item quantity="one">נסה שוב בעוד שנייה אחת</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"נסה שוב מאוחר יותר"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"החלק מטה מהחלק העליון כדי לצאת ממסך מלא."</string>
<string name="done_label" msgid="2093726099505892398">"בוצע"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"כדי לעזור בשיפור חיי הסוללה, תכונת החיסכון בסוללה מצמצמת את פעולות המכשיר ומגבילה רטט, שירותי מיקום ואת רוב נתוני הרקע. אימייל, העברת הודעות ואפליקציות אחרות המסתמכות על סנכרון עשויות שלא להתעדכן, אלא אם תפתח אותן.\n\nתכונת החיסכון בסוללה מושבתת אוטומטית כשהמכשיר בטעינה."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"עד לסיום ההשבתה בשעה <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"עד לסיום זמן ההשבתה"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"למשך דקה אחת (עד <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"למשך %1$d דקות (עד <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"למשך שעה אחת (עד <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"למשך %1$d שעות (עד <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"למשך דקה אחת"</item>
- <item quantity="other" msgid="6924190729213550991">"למשך %d דקות"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"למשך שעה אחת"</item>
- <item quantity="other" msgid="5408537517529822157">"למשך %d שעות"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="two">למשך %d דקות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">למשך %1$d דקות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">למשך %1$d דקות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">למשך דקה אחת (עד <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="two">למשך %d שעות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">למשך %d שעות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">למשך %d שעות (עד <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">למשך שעה אחת (עד <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="two">למשך %d דקות</item>
+ <item quantity="many">למשך %d דקות</item>
+ <item quantity="other">למשך %d דקות</item>
+ <item quantity="one">למשך דקה אחת</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="two">למשך %d שעות</item>
+ <item quantity="many">למשך %d שעות</item>
+ <item quantity="other">למשך %d שעות</item>
+ <item quantity="one">למשך שעה אחת</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"עד <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"ללא הגבלה"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"כווץ"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 27cce45..2efd676 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIMカードはPUKでロックされています。ロックを解除するにはPUKコードを入力してください。"</string>
<string name="needPuk2" msgid="4526033371987193070">"SIMカードのロック解除のためPUK2を入力します。"</string>
<string name="enablePin" msgid="209412020907207950">"SIM/RUIMロックを有効にしてください。"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。この回数を超えるとSIMがロックされます。"</item>
- <item quantity="other" msgid="7530597808358774740">"入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。この回数を超えるとSIMがロックされます。"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">入力できるのはあと<xliff:g id="NUMBER_1">%d</xliff:g>回です。この回数を超えるとSIMがロックされます。</item>
+ <item quantity="one">入力できるのはあと<xliff:g id="NUMBER_0">%d</xliff:g>回です。この回数を超えるとSIMがロックされます。</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"着信時の発信者番号"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>がタッチガイドをONにしようとしています。タッチガイドをONにすると、指の位置にあるアイテムの説明を読み上げたり表示したりできます。また、携帯端末を通常とは違うジェスチャーで操作できます。"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1か月前"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1か月前"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1秒前"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1分前"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g>分前"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1時間前"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>時間前"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">過去<xliff:g id="COUNT_1">%d</xliff:g>日間</item>
+ <item quantity="one">過去<xliff:g id="COUNT_0">%d</xliff:g>日間</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"先月"</string>
<string name="older" msgid="5211975022815554840">"もっと前"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"昨日"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g>日前"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1秒後"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g>秒後"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1分後"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g>分後"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1時間後"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g>時間後"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"明日"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g>日後"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1秒前"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1分前"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g>分前"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1時間前"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g>時間前"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"昨日"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g>日前"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1秒後"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g>秒後"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1分後"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g>分後"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1時間後"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g>時間後"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"明日"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g>日後"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>年"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"週間"</string>
<string name="year" msgid="4001118221013892076">"年"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1秒"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>秒"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1分"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>分"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1時間"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>時間"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>秒</item>
+ <item quantity="one">1秒</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>分</item>
+ <item quantity="one">1分</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>時間</item>
+ <item quantity="one">1時間</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"なし"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"着信音"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"不明な着信音"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fiを利用できます"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fiを利用できます"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Wi-Fiオープンネットワークが利用できます"</item>
- <item quantity="other" msgid="7915895323644292768">"Wi-Fiオープンネットワークが利用できます"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">複数のWi-Fiネットワークが利用できます</item>
+ <item quantity="one">Wi-Fiネットワークが利用できます</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">複数のWi-Fiオープンネットワークが利用できます</item>
+ <item quantity="one">Wi-Fiオープンネットワークが利用できます</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fiネットワークにログイン"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ネットワークにログイン"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"メディアデバイスとして接続"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"カメラとして接続"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDIデバイスとして接続"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"インストーラとして接続"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USBアクセサリを接続しました"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"USB接続方法を変更するにはタップしてください。"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1件一致"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>件"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>件(<xliff:g id="TOTAL">%d</xliff:g>件中)</item>
+ <item quantity="one">1件一致</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"完了"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USBストレージのマウント解除中..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SDカードのマウント解除中..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PINが短すぎます。4桁以上にしてください。"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1秒後に再試行"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g>秒後に再試行"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>秒後にもう一度お試しください</item>
+ <item quantity="one">1秒後にもう一度お試しください</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"しばらくしてから再試行"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"全画面表示を終了するには、上から下にスワイプ"</string>
<string name="done_label" msgid="2093726099505892398">"完了"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使用するその他のアプリは、起動しても更新されないことがあります。\n\nバッテリーセーバーは端末の充電中は自動的にOFFになります。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>にダウンタイムが終わるまで"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"ダウンタイム終了まで"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1分間(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>まで)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d分間(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>まで)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1時間(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>まで)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d時間(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>まで)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1分"</item>
- <item quantity="other" msgid="6924190729213550991">"%d分"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1時間"</item>
- <item quantity="other" msgid="5408537517529822157">"%d時間"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d分間(<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>まで)</item>
+ <item quantity="one">1分間(<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>まで)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d時間(<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>まで)</item>
+ <item quantity="one">1時間(<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>まで)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d分</item>
+ <item quantity="one">1分</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d時間</item>
+ <item quantity="one">1時間</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>まで"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"制限なし"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"折りたたむ"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 421c3e2..a7fac00 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"თქვენი SIM ბარათი დაბლოკილია PUK კოდით. განბლოკვისთვის შეიყვანეთ PUK კოდი."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM ბარათის განსაბლოკად აკრიფეთ PUK2."</string>
<string name="enablePin" msgid="209412020907207950">"წარუმატებელი მცდელობა. ჩართეთ SIM/RUIM ჩაკეტვა."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა, სანამ SIM დაიბლოკებოდეს."</item>
- <item quantity="other" msgid="7530597808358774740">"თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა, სანამ SIM დაიბლოკებოდეს."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">თქვენ დაგრჩათ <xliff:g id="NUMBER_1">%d</xliff:g> მცდელობა, სანამ SIM დაიბლოკება.</item>
+ <item quantity="one">თქვენ დაგრჩათ <xliff:g id="NUMBER_0">%d</xliff:g> მცდელობა, სანამ SIM დაიბლოკება.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"შემომავალი ზარის აბონენტის ID"</string>
@@ -1131,73 +1131,12 @@
<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">"ერთი თვის წინ"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"უფრო ადრე, ვიდრე ერთი თვის წინ"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 წამის წინ"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> წამის წინ"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 წუთის უკან"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> წუთის წინ"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 საათის წინ"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> საათის წინ"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> ბოლო <xliff:g id="COUNT_1">%d</xliff:g> დღეს</item>
+ <item quantity="one"> ბოლო <xliff:g id="COUNT_0">%d</xliff:g> დღეს</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"გასული თვე"</string>
<string name="older" msgid="5211975022815554840">"უფრო ძველი"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"გუშინ"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> დღის წინ"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 წამში"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> წამში"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 წუთში"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> წუთში"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 საათში"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> საათში"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ხვალ"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> დღეში"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 წმ. წინ"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> წამის წინ"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 წუთის წინ"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> წუთის წინ"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 საათის წინ"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> საათის წინ"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"გუშინ"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> დღის წინ"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 წამში"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> წამის წინ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 წუთში"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> წუთში"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 საათში"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> საათში"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ხვალ"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> დღეში"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"თარიღი: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>-ზე"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> წელს"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"კვირა"</string>
<string name="year" msgid="4001118221013892076">"წელი"</string>
<string name="years" msgid="6881577717993213522">"წელი"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 წამი"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> წამი"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 წუთი"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> წუთი"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 საათი"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> საათში"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> წამი</item>
+ <item quantity="one">1 წამი</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> წუთი</item>
+ <item quantity="one">1 წუთი</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> საათი</item>
+ <item quantity="one">1 საათი</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"არც ერთი"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ზარები"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"უცნობი ზარი"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi ქსელი ხელმისაწვდომია"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi ქსელები ხელმისაწვდომია."</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"ხელმისაწვდომი Wi-Fi ქსელების გახსნა"</item>
- <item quantity="other" msgid="7915895323644292768">"ხელმისაწვდომი Wi-Fi ქსელების გახსნა"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">ხელმისაწვდომია Wi-Fi ქსელები</item>
+ <item quantity="one">ხელმისაწვდომია Wi-Fi ქსელი</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">ხელმისაწვდომია ღია Wi-Fi ქსელები</item>
+ <item quantity="one">ხელმისაწვდომია ღია Wi-Fi ქსელი</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi ქსელთან დაკავშირება"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ქსელში შესვლა"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"დაკავშირებულია როგორც მედია მოწყობილობა"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"დაკავშირებულია როგორც კამერა"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"დაკავშირებული როგორც MIDI მოწყობილობა"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"დაკავშირებულია როგორც დამყენებელი"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"დაკავშირებულია USB აქსესუართან"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"შეეხეთ USB-ის სხვა პარამეტრების სანახავად."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 დამთხვევა"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> <xliff:g id="TOTAL">%d</xliff:g>-დან"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>, სულ: <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 დამთხვევა</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"დასრულდა"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB მეხსიერების გათიშვა…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"მიმდინარეობს SD ბარათის მოხსნა…"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN ძალიან მოკლეა. უნდა შედგებოდეს სულ ცოტა 4 ციფრისგან."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"კიდევ ერთხელ სცადეთ 1 წამში"</item>
- <item quantity="other" msgid="4730868920742952817">"კიდევ ერთხელ სცადეთ <xliff:g id="COUNT">%d</xliff:g> წამში"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">ხელახლა სცადეთ <xliff:g id="COUNT">%d</xliff:g> წამში</item>
+ <item quantity="one">ხელახლა სცადეთ 1 წამში</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"სცადეთ მოგვიანებით"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"ჩამოასრიალეთ ზევიდან სრული ეკრანის დასახურად."</string>
<string name="done_label" msgid="2093726099505892398">"დასრულდა"</string>
@@ -1838,8 +1778,8 @@
<string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="7570091317001980053">"მიმაგრების გასაუქმებლად ერთდროულად შეეხეთ და არ აუშვათ ღილაკებს „უკან“ და „გადახედვა“."</string>
- <string name="lock_to_app_toast_accessible" msgid="8239120109365070664">"ამ ეკრანისთვის მიმაგრების გასაუქმებლად შეეხეთ და არ აუშვათ ღილაკებს „გადახედვა“."</string>
+ <string name="lock_to_app_toast" msgid="7570091317001980053">"მიმაგრების გასაუქმებლად ერთდროულად შეეხეთ და არ აუშვათ ღილაკებს „უკან“ და „მიმოხილვა“."</string>
+ <string name="lock_to_app_toast_accessible" msgid="8239120109365070664">"ამ ეკრანისთვის მიმაგრების გასაუქმებლად, შეეხეთ და არ აუშვათ „მიმოხილვა“-ს."</string>
<string name="lock_to_app_toast_locked" msgid="8739004135132606329">"ეკრანი დაფიქსირებული. ფიქსაციის მოხსნა თქვენო ორგანიზაციის მიერ ნებადართული არ არის."</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"ეკრანი დაფიქსირდა"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"ეკრანს ფიქსაცია მოეხსნა"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ელემენტის მოქმედების ვადის გაუმჯობესებისათვის, ელემენტის დამზოგი ამცირებს თქვენი მოწყობილობის შესრულებას და ზღუდავს ვიბრაციას, ადგილმდებარეობის მომსახურებებს და ძირითად ფონურ მონაცემებს. ელ-ფოსტა, შეტყობინებები და სხვა სინქრონიზაციაზე დაყრდნობილი აპლიკაციების განახლება არ მოხდება მათ გახსნეამდე. \n\n ელემენტის დამზოგველი ავტომატურად გამოირთვება, როდესაც თქვენს მოწყობილობას დამტენთან შეაერთებთ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"დანამ თქვენი კავშირგარეშე დრო დასრულდებოდეს <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ზე"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"სანამ ავარიული პაუზა დასრულდებოდეს"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ერთი წუთის განმავლობაში (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>-მდე)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d წუთის განმავლობაში (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>-მდე)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ერთი საათის განმავლობაში (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>-მდე)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d საათის განმავლობაში (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>-მდე)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item>
- <item quantity="other" msgid="6924190729213550991">"%d წუთით"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ერთი საათით"</item>
- <item quantity="other" msgid="5408537517529822157">"%d საათით"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d წუთის განმავლობაში (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>-მდე)</item>
+ <item quantity="one">ერთი წუთის განმავლობაში (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>-მდე)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d საათის განმავლობაში (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>-მდე)</item>
+ <item quantity="one">ერთი საათის განმავლობაში (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>-მდე)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d წუთის განმავლობაში</item>
+ <item quantity="one">ერთი წუთის განმავლობაში</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d საათის განმავლობაში</item>
+ <item quantity="one">ერთი საათის განმავლობაში</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-მდე"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"სამუდამოდ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"აკეცვა"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 7fad880..02fcd62 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM картаңыз PUK арқылы бекітілген. Ашу үшін PUK кодын теріңіз."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM картасын ашу үшін PUK2 кодын теріңіз."</string>
<string name="enablePin" msgid="209412020907207950">"Сәтсіз, SIM/RUIM бекітпесін қосыңыз."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"<xliff:g id="NUMBER">%d</xliff:g> әрекеттен кейін SIM бекітіледі."</item>
- <item quantity="other" msgid="7530597808358774740">"<xliff:g id="NUMBER">%d</xliff:g> әрекеттен кейін SIM бекітіледі."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">SIM картасының бекітілуіне <xliff:g id="NUMBER_1">%d</xliff:g> әрекет қалды.</item>
+ <item quantity="one">SIM картасының бекітілуіне <xliff:g id="NUMBER_0">%d</xliff:g> әрекет қалды.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI (Халықаралық мобильдік құрылғы анықтағышы)"</string>
<string name="meid" msgid="4841221237681254195">"MEID (ұялы құрылғы анықтағыш)"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Келген қоңырау шалушының жеке анықтағышы"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 секунд бұрын"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> секунд бұрын"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 минут бұрын"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> минут бұрын"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 сағат бұрын"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> сағат бұрын"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Соңғы <xliff:g id="COUNT_1">%d</xliff:g> күн</item>
+ <item quantity="one">Соңғы <xliff:g id="COUNT_0">%d</xliff:g> күн</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Соңғы ай"</string>
<string name="older" msgid="5211975022815554840">"Ескілеу"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"кеше"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> күн бұрын"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 секундта"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> секундта"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 минутта"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> минутта"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 сағатта"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> сағатта"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ертең"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> күнде"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 секунд бұрын"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> секунд бұрын"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 минут бұрын"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> минут бұрын"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 сағат бұрын"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> сағат бұрын"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"кеше"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> күн бұрын"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 секундта"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> секундта"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 минутта"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> минутта"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 сағатта"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> сағатта"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ертең"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> күнде"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> күні"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> уақытында"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> жылда"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"апталар"</string>
<string name="year" msgid="4001118221013892076">"жыл"</string>
<string name="years" msgid="6881577717993213522">"жылдар"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунд"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунд"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 минут"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минут"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 сағат"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> сағат"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="one">1 секунд</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минут</item>
+ <item quantity="one">1 минут</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> сағат</item>
+ <item quantity="one">1 сағат</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ешқандай"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Бастапқы қоңырау әуендері"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Белгісіз қоңырау әуені"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi желісі қол жетімді"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi желілері қол жетімді"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Ашық Wi-Fi желісі қол жетімді"</item>
- <item quantity="other" msgid="7915895323644292768">"Ашық Wi-Fi желілері қол жетімді"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi желілері қол жетімді</item>
+ <item quantity="one">Wi-Fi желісі қол жетімді</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Ашық Wi-Fi желілері қол жетімді</item>
+ <item quantity="one">Ашық Wi-Fi желісі қол жетімді</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi желісіне кіру"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Желіге кіру"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Жарайды"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Медиа құралы ретінде қосылған"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Камера ретінде жалғанған"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI құрылғысы ретінде қосылу орындалды"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Орнату құрылғысына жалғанған"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB жабдығына қосылған"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Басқа USB oпцияларын түрту."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 сәйкестік"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>, барлығы <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> ішінен <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1 сәйкестік</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Орындалды"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB жадын шығаруда…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD картасын шығаруда…"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN тым қысқа. Кем дегенде 4 бірлік болуы тиіс."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 секундтан кейін қайта әрекеттеніңіз"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> секундтан кейін қайта әрекеттеніңіз"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Әрекетті <xliff:g id="COUNT">%d</xliff:g> секундтан кейін қайталаңыз</item>
+ <item quantity="one">Әрекетті 1 секундтан кейін қайталаңыз</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Кейінірек қайта әрекеттеніңіз."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Толық экраннан шығу үшін саусағыңызды жоғарыдан төмен қарай жылжытыңыз."</string>
<string name="done_label" msgid="2093726099505892398">"Орындалды"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Батареяның қызмет көрсету мерзімін жақсарту үшін батарея үнемдегіш құрылғының өнімділігін төмендетеді және дірілді, орынды анықтау қызметтерін және фондық деректердің көпшілігін шектейді. Электрондық пошта, хабар алмасу және синхрондауға негізделген басқа қолданбалар ашқанша жаңартылмауы мүмкін.\n\nБатарея үнемдегіш құрылғы зарядталып жатқанда автоматты түрде өшеді."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> уақытында әрекетсіздік аяқталғанша"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Бос тұру уақыты аяқталғанша"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Бір минут бойы (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> дейін)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d минут бойы (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> дейін)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Бір сағат бойы (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> дейін)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d сағат бойы (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> дейін)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Бір минут бойы"</item>
- <item quantity="other" msgid="6924190729213550991">"%d минут бойы"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Бір сағат бойы"</item>
- <item quantity="other" msgid="5408537517529822157">"%d сағат бойы"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d минут бойы (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> дейін)</item>
+ <item quantity="one">Бір минут бойы (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> дейін)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d сағат бойы (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> дейін)</item>
+ <item quantity="one">Бір сағат бойы (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> дейін)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d минут бойы</item>
+ <item quantity="one">Бір минут бойы</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d сағат бойы</item>
+ <item quantity="one">Бір сағат бойы</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дейін"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Белгісіз уақыт бойы"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Тасалау"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 6f38aec..491688c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ស៊ីមកាតរបស់អ្នកជាប់កូដ PUK ។ បញ្ចូលកូដ PUK ដើម្បីដោះសោ។"</string>
<string name="needPuk2" msgid="4526033371987193070">"បញ្ចូលកូដ PUK2 ដើម្បីដោះសោស៊ីមកាត។"</string>
<string name="enablePin" msgid="209412020907207950">"បរាជ័យ, បើកការចាក់សោស៊ីម / RUIM ។"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់មុនពេលស៊ីមត្រូវបានចាក់សោ។"</item>
- <item quantity="other" msgid="7530597808358774740">"អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់មុនពេលស៊ីមត្រូវបានចាក់សោ។"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_1">%d</xliff:g> ដងទៀត មុនពេលស៊ីមត្រូវចាក់សោ។</item>
+ <item quantity="one">អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_0">%d</xliff:g> ដងទៀត មុនពេលស៊ីមត្រូវចាក់សោ។</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"លេខសម្គាល់អ្នកហៅចូល"</string>
@@ -1131,73 +1131,12 @@
<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">"មុនពេល ១ ខែមុន"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"១ វិនាទីមុន"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> វិនាទីមុន"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"១ នាទីមុន"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> នាទីមុន"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"១ ម៉ោងមុន"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ម៉ោងមុន"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> <xliff:g id="COUNT_1">%d</xliff:g> ថ្ងៃចុងក្រោយ</item>
+ <item quantity="one"> <xliff:g id="COUNT_0">%d</xliff:g> ថ្ងៃចុងក្រោយ</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"ខែមុន"</string>
<string name="older" msgid="5211975022815554840">"ចាស់ជាង"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ម្សិលមិញ"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> ថ្ងៃមុន"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"ក្នុងរយៈពេល ១ វិនាទី"</item>
- <item quantity="other" msgid="1241926116443974687">"ក្នុងរយៈពេល <xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"ក្នុងរយៈពេល ១ នាទី"</item>
- <item quantity="other" msgid="3330713936399448749">"រយៈពេល <xliff:g id="COUNT">%d</xliff:g> នាទី"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"រយៈពេល ១ ម៉ោង"</item>
- <item quantity="other" msgid="547290677353727389">"រយៈពេល <xliff:g id="COUNT">%d</xliff:g> ម៉ោង"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ថ្ងៃស្អែក"</item>
- <item quantity="other" msgid="5109449375100953247">"រយៈពេល <xliff:g id="COUNT">%d</xliff:g> ថ្ងៃ"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"១ វិនាទីមុន"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> វិនាទីមុន"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"១ នាទីមុន"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> នាទីមុន"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"១ ម៉ោងមុន"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ម៉ោងមុន"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ម្សិលមិញ"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> ថ្ងៃមុន"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"ក្នុងពេល 1 វិនាទី"</item>
- <item quantity="other" msgid="5495880108825805108">"ក្នុងពេល <xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"ក្នុងពេល 1 នាទី"</item>
- <item quantity="other" msgid="4216113292706568726">"នៅរយៈពេល <xliff:g id="COUNT">%d</xliff:g> នាទី"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ក្នុងរយៈពេល ១ ម៉ោង"</item>
- <item quantity="other" msgid="3705373766798013406">"ក្នុងរយៈពេល <xliff:g id="COUNT">%d</xliff:g> ម៉ោង"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ថ្ងៃស្អែក"</item>
- <item quantity="other" msgid="2973062968038355991">"ក្នុងរយៈពេល <xliff:g id="COUNT">%d</xliff:g> ថ្ងៃ"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"នៅ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"នៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ក្នុងឆ្នាំ <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍"</string>
<string name="year" msgid="4001118221013892076">"ឆ្នាំ"</string>
<string name="years" msgid="6881577717993213522">"ឆ្នាំ"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 វិនាទី"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"១ នាទី"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> នាទី"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"១ ម៉ោង"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ម៉ោង"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> វិនាទី</item>
+ <item quantity="one">1 វិនាទី</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> នាទី</item>
+ <item quantity="one">1 នាទី</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ម៉ោង</item>
+ <item quantity="one">1 ម៉ោង</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>
@@ -1335,14 +1274,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"គ្មាន"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"សំឡេងរោទ៍"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"សំឡេងរោទ៍មិនស្គាល់"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"មានបណ្ដាញវ៉ាយហ្វាយ"</item>
- <item quantity="other" msgid="4192424489168397386">"មានបណ្ដាញវ៉ាយហ្វាយ"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"បើកបណ្ដាញវ៉ាយហ្វាយដែលមាន"</item>
- <item quantity="other" msgid="7915895323644292768">"មានបណ្ដាញវ៉ាយហ្វាយបើក"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">មានបណ្តាញ Wi-Fi</item>
+ <item quantity="one">មានបណ្តាញ Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">បើកបណ្តាញ Wi-Fi ដែលមាន</item>
+ <item quantity="one">បើកបណ្តាញ Wi-Fi ដែលមាន</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ចូលបណ្ដាញវ៉ាយហ្វាយ"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ចូលក្នុងបណ្ដាញ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1418,6 +1357,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"យល់ព្រម"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"បានតភ្ជាប់ជាឧបករណ៍ផ្ទុក"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"បានភ្ជាប់ជាម៉ាស៊ីនថត"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"បានភ្ជាប់ជាឧបករណ៍មីឌី"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"បានភ្ជាប់ជាកម្មវិធីដំឡើង"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"បានភ្ជាប់ឧបករណ៍យូអេសប៊ី"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"ប៉ះ ដើម្បីមើលជម្រើសយូអេសប៊ីផ្សេង។"</string>
@@ -1533,10 +1473,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"១ ប្រកួត"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> នៃ <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> នៃ <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">ការប្រកួត 1</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"រួចរាល់"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"កំពុងផ្ដាច់ឧបករណ៍យូអេសប៊ី..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"កំពុងផ្ដាច់កាតអេសឌី..."</string>
@@ -1822,10 +1762,10 @@
<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_too_short" msgid="8173982756265777792">"កូដ PIN ខ្លីពេក។ ត្រូវតែមានយ៉ាងហោចណាស់ ៤ តួ។"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"ព្យាយាមម្ដងទៀតក្នុងរយៈពេល ១វិនាទី។"</item>
- <item quantity="other" msgid="4730868920742952817">"សូមព្យាយាមម្ដងទៀតក្នុងរយៈពេល <xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">ព្យាយាមម្តងទៀតក្នុងរយៈពេល <xliff:g id="COUNT">%d</xliff:g> វិនាទី</item>
+ <item quantity="one">ព្យាយាមម្តងទៀតក្នុងរយៈពេល 1 វិនាទី</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"សូមព្យាយាមម្ដងទៀតនៅពេលក្រោយ។"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"អូសពីលើចុះក្រោម ដើម្បីចេញពីការបង្ហាញពេញអេក្រង់។"</string>
<string name="done_label" msgid="2093726099505892398">"រួចរាល់"</string>
@@ -1851,22 +1791,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ដើម្បីជួយឲ្យថាមពលថ្មប្រសើរឡើង កម្មវិធីសន្សំសំចៃថាមពលថ្មកាត់បន្ថយប្រតិបត្តិការឧបករណ៍របស់អ្នក និងកម្រិតភាពញ័រ សេវាកម្មទីតាំង និងទិន្នន័យផ្ទៃខាងក្រោយស្ទើរតែទាំងអស់។ ការផ្ញើសារអ៊ីម៉ែល និងកម្មវិធីផ្សេងទៀតដែលពឹងផ្អែកលើការធ្វើសមកាលកម្មអាចនឹងមិនធ្វើបច្ចុប្បន្នភាពទេ លុះត្រាតែអ្នកបើកពួកវា។\n\nកម្មវិធីសន្សំសំចៃបិទដោយស្វ័យប្រវត្តិ នៅពេលដែលឧបករណ៍របស់អ្នកកំពុងសាកថ្ម។"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"រហូតដល់ម៉ោងសម្រាក ឬរវល់របស់អ្នកបញ្ចប់នៅ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"រហូតដល់ម៉ោងរាប់ថយក្រោយចប់"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"សម្រាប់មួយនាទី (រហូតដល់ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"សម្រាប់ %1$d នាទី (រហូតដល់ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"សម្រាប់មួយម៉ោង (រហូតដល់ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"សម្រាប់ %1$d ម៉ោង (រហូតដល់ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"សម្រាប់មួយនាទី"</item>
- <item quantity="other" msgid="6924190729213550991">"សម្រាប់ %d នាទី"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"សម្រាប់មួយម៉ោង"</item>
- <item quantity="other" msgid="5408537517529822157">"សម្រាប់ %d ម៉ោង"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">រយៈពេល %1$d នាទី (រហូតដល់ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">រយៈពេលមួយនាទី (រហូតដល់ <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">រយៈពេល %1$d ម៉ោង (រហូតដល់ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">រយៈពេលមួយម៉ោង (រហូតដល់ <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">រយៈពេល %d នាទី</item>
+ <item quantity="one">រយៈពេលមួយនាទី</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">រយៈពេល %d ម៉ោង</item>
+ <item quantity="one">រយៈពេលមួយម៉ោង</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"រហូតដល់ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"គ្មានកំណត់"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"បង្រួម"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 421c103..92aa838 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ನಿಮ್ಮ ಸಿಮ್ ಕಾರ್ಡ್ PUK-ಲಾಕ್ ಆಗಿದೆ. ಅದನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಲು PUK ಕೋಡ್ ಟೈಪ್ ಮಾಡಿ."</string>
<string name="needPuk2" msgid="4526033371987193070">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ಲಾಕ್ ಮಾಡಲು PUK2 ಟೈಪ್ ಮಾಡಿ."</string>
<string name="enablePin" msgid="209412020907207950">"ಯಶಸ್ವಿಯಾಗಿಲ್ಲ, ಸಿಮ್/RUIM ಲಾಕ್ ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"ಸಿಮ್ ಲಾಕ್ ಆಗುವುದಕ್ಕಿಂತ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನ ಬಾಕಿ ಉಳಿದಿದೆ."</item>
- <item quantity="other" msgid="7530597808358774740">"ಸಿಮ್ ಲಾಕ್ ಆಗುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ಒಳಬರುವ ಕರೆಮಾಡುವವರ ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 ಸೆಕೆಂಡಿನ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 ನಿಮಿಷದ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ಗಂಟೆ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">ಕಳೆದ <xliff:g id="COUNT_1">%d</xliff:g> ದಿನಗಳು</item>
+ <item quantity="other">ಕಳೆದ <xliff:g id="COUNT_1">%d</xliff:g> ದಿನಗಳು</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"ಕಳೆದ ತಿಂಗಳು"</string>
<string name="older" msgid="5211975022815554840">"ಹಳೆಯದು"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ನಿನ್ನೆ"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> ದಿನಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 ಸೆಕೆಂಡಿನಲ್ಲಿ"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 ನಿಮಿಷದಲ್ಲಿ"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 ಗಂಟೆಯಲ್ಲಿ"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ನಾಳೆ"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> ದಿನಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 ಸೆಕೆಂಡಿನ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 ನಿಮಿಷದ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ಗಂಟೆ ಹಿಂದೆ"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ನಿನ್ನೆ"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> ದಿನಗಳ ಹಿಂದೆ"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 ಸೆಕೆಂಡಿನಲ್ಲಿ"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 ನಿಮಿಷದಲ್ಲಿ"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 ಗಂಟೆಯಲ್ಲಿ"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳಲ್ಲಿ"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ನಾಳೆ"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> ದಿನಗಳಲ್ಲಿ"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> ರಂದು"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> ರಲ್ಲಿ"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> ರಲ್ಲಿ"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"ವಾರಗಳು"</string>
<string name="year" msgid="4001118221013892076">"ವರ್ಷ"</string>
<string name="years" msgid="6881577717993213522">"ವರ್ಷಗಳು"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 ಸೆಕೆಂಡು"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳು"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 ನಿಮಿಷ"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳು"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ಗಂಟೆ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳು"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳು</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳು</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳು</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ನಿಮಿಷಗಳು</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ಗಂಟೆಗಳು</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ಯಾವುದೂ ಇಲ್ಲ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ರಿಂಗ್ಟೋನ್ಗಳು"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"ಅಜ್ಞಾತ ರಿಂಗ್ಟೋನ್"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿದೆ"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"ಮುಕ್ತ Wi-Fi ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿದೆ"</item>
- <item quantity="other" msgid="7915895323644292768">"ಮುಕ್ತ Wi-Fi ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
+ <item quantity="other">ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
+ <item quantity="other">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿವೆ</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ನೆಟ್ವರ್ಕ್ಗೆ ಸೈನ್ ಮಾಡಿ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ಸರಿ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"ಮಾಧ್ಯಮ ಸಾಧನದ ರೂಪದಲ್ಲಿ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"ಕ್ಯಾಮರಾದಂತೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI ಸಾಧನದಂತೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ಸ್ಥಾಪಕದಂತೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB ಪರಿಕರಕ್ಕೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"ಇತರ USB ಆಯ್ಕೆಗಳಿಗಾಗಿ ಸ್ಪರ್ಶಿಸಿ."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 ಹೊಂದಾಣಿಕೆ"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> ರಲ್ಲಿ <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> ರಲ್ಲಿ <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> ರಲ್ಲಿ <xliff:g id="INDEX">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"ಮುಗಿದಿದೆ"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB ಸಂಗ್ರಹಣೆಯ ಅಳವಡಿಕೆ ತೆಗೆಯಲಾಗುತ್ತಿದೆ…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD ಕಾರ್ಡ್ ಅಳವಡಿಕೆ ತೆಗೆಯಲಾಗುತ್ತಿದೆ…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"ನಿರ್ಬಂಧಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಪಿನ್ ರಚಿಸಿ"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"ಪಿನ್ ಗಳು ಹೊಂದಿಕೆಯಾಗುತ್ತಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"ಪಿನ್ ತುಂಬಾ ಚಿಕ್ಕದಾಗಿದೆ. ಕನಿಷ್ಟ ಪಕ್ಷ 4 ಅಂಕಿಗಳಾಗಿರಬೇಕು."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 ಸೆಕೆಂಡಿನಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"ಪೂರ್ಣ ಪರದೆಯನ್ನು ನಿರ್ಗಮಿಸಲು ಮೇಲಿನಿಂದ ಕೆಳಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ."</string>
<string name="done_label" msgid="2093726099505892398">"ಮುಗಿದಿದೆ"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ನಿಮ್ಮ ಬ್ಯಾಟರಿಯ ಬಾಳಿಕೆಯನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು, ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ವೈಬ್ರೇಷನ್, ಸ್ಥಳ ಸೇವೆಗಳು ಹಾಗೂ ಹೆಚ್ಚಿನ ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ. ಸಿಂಕ್ ಮಾಡುವುದನ್ನು ಅವಲಂಬಿಸಿರುವ ಇಮೇಲ್, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ, ಮತ್ತು ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳು ನೀವು ತೆರೆಯದ ಹೊರತು ನವೀಕರಣಗೊಳ್ಳುವುದಿಲ್ಲ.\n\nನಿಮ್ಮ ಸಾಧನವು ಚಾರ್ಜ್ ಆಗುತ್ತಿರುವ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ಆಫ್ ಆಗುತ್ತದೆ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ನಿಮ್ಮ ಅಲಭ್ಯತೆ ಕೊನೆಗೊಳ್ಳುವವರೆಗೆ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"ನಿಮ್ಮ ಸ್ಥಗಿತಕಾಲ ಕೊನೆಗೊಳ್ಳುವವರೆಗೆ"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ಒಂದು ನಿಮಿಷದವರೆಗೆ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ವರೆಗೆ)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d ನಿಮಿಷಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ವರೆಗೆ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ಒಂದು ಗಂಟೆಯವರೆಗೆ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ವರೆಗೆ)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d ಗಂಟೆಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> ವರೆಗೆ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ಒಂದು ನಿಮಿಷದವರೆಗೆ"</item>
- <item quantity="other" msgid="6924190729213550991">"%d ನಿಮಿಷಗಳವರೆಗೆ"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ಒಂದು ಗಂಟೆಯವರೆಗೆ"</item>
- <item quantity="other" msgid="5408537517529822157">"%d ಗಂಟೆಗಳವರೆಗೆ"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d ನಿಮಿಷಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ವರೆಗೆ)</item>
+ <item quantity="other">%1$d ನಿಮಿಷಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ವರೆಗೆ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d ಗಂಟೆಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ವರೆಗೆ)</item>
+ <item quantity="other">%1$d ಗಂಟೆಗಳವರೆಗೆ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> ವರೆಗೆ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d ನಿಮಿಷಗಳವರೆಗೆ</item>
+ <item quantity="other">%d ನಿಮಿಷಗಳವರೆಗೆ</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d ಗಂಟೆಗಳವರೆಗೆ</item>
+ <item quantity="other">%d ಗಂಟೆಗಳವರೆಗೆ</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"ಅನಿರ್ದಿಷ್ಟವಾಗಿ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ಸಂಕುಚಿಸು"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 94c60d9..027f994 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM 카드의 PUK가 잠겨 있습니다. 잠금해제하려면 PUK 코드를 입력하세요."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM 카드 잠금을 해제하려면 PUK2를 입력하세요."</string>
<string name="enablePin" msgid="209412020907207950">"실패했습니다. SIM/RUIM 잠금을 사용 설정하세요."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"<xliff:g id="NUMBER">%d</xliff:g>회 이상 실패할 경우 SIM이 잠깁니다."</item>
- <item quantity="other" msgid="7530597808358774740">"<xliff:g id="NUMBER">%d</xliff:g>회 이상 실패할 경우 SIM이 잠깁니다."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g>번 더 실패하면 SIM이 잠깁니다.</item>
+ <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g>번 더 실패하면 SIM이 잠깁니다.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"발신자 번호"</string>
@@ -1131,73 +1131,12 @@
<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">"한 달 전"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"한 달 전"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1초 전"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g>초 전"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1분 전"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g>분 전"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1시간 전"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>시간 전"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">지난 <xliff:g id="COUNT_1">%d</xliff:g>일</item>
+ <item quantity="one">지난 <xliff:g id="COUNT_0">%d</xliff:g>일</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"지난 달"</string>
<string name="older" msgid="5211975022815554840">"이전"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"어제"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g>일 전"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1초 내"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g>초 후"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1분 후"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g>분 후"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1시간 후"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g>시간 후"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"내일"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g>일 후"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1초 전"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g>초 전"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1분 전"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g>분 전"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1시간 전"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g>시간 전"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"어제"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g>일 전"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1초 후"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g>초 후"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1분 후"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g>분 후"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1시간 후"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g>시간 후"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"내일"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g>일 후"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>년"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"주"</string>
<string name="year" msgid="4001118221013892076">"년"</string>
<string name="years" msgid="6881577717993213522">"년"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1초"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>초"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1분"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>분"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1시간"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>시간"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>초</item>
+ <item quantity="one">1초</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>분</item>
+ <item quantity="one">1분</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>시간</item>
+ <item quantity="one">1시간</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"없음"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"벨소리"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"알 수 없는 벨소리"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi 네트워크 사용 가능"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi 네트워크 사용 가능"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"개방형 Wi-Fi 네트워크 사용 가능"</item>
- <item quantity="other" msgid="7915895323644292768">"개방형 Wi-Fi 네트워크 사용 가능"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi 네트워크 사용 가능</item>
+ <item quantity="one">Wi-Fi 네트워크 사용 가능</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">개방형 Wi-Fi 네트워크 사용 가능</item>
+ <item quantity="one">개방형 Wi-Fi 네트워크 사용 가능</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi 네트워크에 로그인"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"네트워크에 로그인"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"확인"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"미디어 기기로 연결됨"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"카메라로 연결됨"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI 기기로 연결됨"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"설치 프로그램으로 연결됨"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB 액세서리에 연결됨"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"다른 USB 옵션을 보려면 터치하세요."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"검색결과 1개"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other">검색결과 <xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">검색결과 1개</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"완료"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB 저장소 마운트 해제 중..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD 카드 마운트 해제 중..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN이 너무 짧습니다. 최소 4자 이상이어야 합니다."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1초 후에 다시 시도하세요."</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g>초 후에 다시 시도하세요."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g>초 후에 다시 시도하세요.</item>
+ <item quantity="one">1초 후에 다시 시도하세요.</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"나중에 다시 시도"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"전체화면을 종료하려면 위에서 아래로 스와이프하세요."</string>
<string name="done_label" msgid="2093726099505892398">"완료"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"배터리 수명 개선을 위해, 배터리 세이버는 기기의 성능을 줄이고 진동, 위치 서비스 및 대부분의 백그라운드 데이터를 제한합니다. 이메일, 메시지 및 동기화에 의존하는 기타 앱은 앱을 열 때까지 업데이트되지 않을 수 있습니다.\n\n배터리 세이버는 기기를 충전 중일 때는 자동으로 사용 중지됩니다."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>에 정지가 종료될 때까지"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"다운타임이 끝날 때까지"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1분(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>까지)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d분(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>까지)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1시간(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>까지)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d시간(<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>까지)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1분 동안"</item>
- <item quantity="other" msgid="6924190729213550991">"%d분 동안"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1시간 동안"</item>
- <item quantity="other" msgid="5408537517529822157">"%d시간 동안"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d분 동안(<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>까지)</item>
+ <item quantity="one">1분 동안(<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>까지)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d시간 동안(<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>까지)</item>
+ <item quantity="one">1시간 동안(<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>까지)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d분 동안</item>
+ <item quantity="one">1분 동안</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d시간 동안</item>
+ <item quantity="one">1시간 동안</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>까지"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"무제한"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"접기"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 898b226..dfb23a3 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -83,10 +83,10 @@
<!-- no translation found for needPuk2 (4526033371987193070) -->
<skip />
<string name="enablePin" msgid="209412020907207950">"Оңунан чыкпады, SIM/RUIM бөгөттөөсүн жандырыңыз."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Сизде SIM бөгөттөлгөнгө чейин <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- <item quantity="other" msgid="7530597808358774740">"Сизде SIM бөгөттөлгөнгө чейин <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Сизде SIM кулпуланганга чейин <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item>
+ <item quantity="one">Сизде SIM кулпуланганга чейин <xliff:g id="NUMBER_0">%d</xliff:g> аракет калды.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<!-- no translation found for ClipMmi (6952821216480289285) -->
@@ -1474,44 +1474,14 @@
<skip />
<!-- no translation found for beforeOneMonthDurationPast (909134546836499826) -->
<skip />
- <!-- no translation found for num_seconds_ago:one (4869870056547896011) -->
- <!-- no translation found for num_seconds_ago:other (3903706804349556379) -->
- <!-- no translation found for num_minutes_ago:one (3306787433088810191) -->
- <!-- no translation found for num_minutes_ago:other (2176942008915455116) -->
- <!-- no translation found for num_hours_ago:one (9150797944610821849) -->
- <!-- no translation found for num_hours_ago:other (2467273239587587569) -->
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
- <!-- no translation found for last_num_days:other (3069992808164318268) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Акыркы <xliff:g id="COUNT_1">%d</xliff:g> күн</item>
+ <item quantity="one">Акыркы <xliff:g id="COUNT_0">%d</xliff:g> күн</item>
+ </plurals>
<!-- no translation found for last_month (3959346739979055432) -->
<skip />
<!-- no translation found for older (5211975022815554840) -->
<skip />
- <!-- no translation found for num_days_ago:one (861358534398115820) -->
- <!-- no translation found for num_days_ago:other (2479586466153314633) -->
- <!-- no translation found for in_num_seconds:one (2729745560954905102) -->
- <!-- no translation found for in_num_seconds:other (1241926116443974687) -->
- <!-- no translation found for in_num_minutes:one (8793095251325200395) -->
- <!-- no translation found for in_num_minutes:other (3330713936399448749) -->
- <!-- no translation found for in_num_hours:one (7164353342477769999) -->
- <!-- no translation found for in_num_hours:other (547290677353727389) -->
- <!-- no translation found for in_num_days:one (5413088743009839518) -->
- <!-- no translation found for in_num_days:other (5109449375100953247) -->
- <!-- no translation found for abbrev_num_seconds_ago:one (1849036840200069118) -->
- <!-- no translation found for abbrev_num_seconds_ago:other (3699169366650930415) -->
- <!-- no translation found for abbrev_num_minutes_ago:one (6361490147113871545) -->
- <!-- no translation found for abbrev_num_minutes_ago:other (851164968597150710) -->
- <!-- no translation found for abbrev_num_hours_ago:one (4796212039724722116) -->
- <!-- no translation found for abbrev_num_hours_ago:other (6889970745748538901) -->
- <!-- no translation found for abbrev_num_days_ago:one (8463161711492680309) -->
- <!-- no translation found for abbrev_num_days_ago:other (3453342639616481191) -->
- <!-- no translation found for abbrev_in_num_seconds:one (5842225370795066299) -->
- <!-- no translation found for abbrev_in_num_seconds:other (5495880108825805108) -->
- <!-- no translation found for abbrev_in_num_minutes:one (562786149928284878) -->
- <!-- no translation found for abbrev_in_num_minutes:other (4216113292706568726) -->
- <!-- no translation found for abbrev_in_num_hours:one (3274708118124045246) -->
- <!-- no translation found for abbrev_in_num_hours:other (3705373766798013406) -->
- <!-- no translation found for abbrev_in_num_days:one (2178576254385739855) -->
- <!-- no translation found for abbrev_in_num_days:other (2973062968038355991) -->
<!-- no translation found for preposition_for_date (9093949757757445117) -->
<skip />
<!-- no translation found for preposition_for_time (5506831244263083793) -->
@@ -1542,18 +1512,18 @@
<skip />
<!-- no translation found for years (6881577717993213522) -->
<skip />
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунда"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 мүнөт"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> мүнөт"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 саат"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> саат"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="one">1 секунд</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> мүнөт</item>
+ <item quantity="one">1 мүнөт</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> саат</item>
+ <item quantity="one">1 саат</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>
@@ -1709,10 +1679,14 @@
<skip />
<!-- no translation found for ringtone_unknown (5477919988701784788) -->
<skip />
- <!-- no translation found for wifi_available:one (6654123987418168693) -->
- <!-- no translation found for wifi_available:other (4192424489168397386) -->
- <!-- no translation found for wifi_available_detailed:one (1634101450343277345) -->
- <!-- no translation found for wifi_available_detailed:other (7915895323644292768) -->
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi тармагы жеткиликтүү</item>
+ <item quantity="one">Wi-Fi тармагы жеткиликтүү</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Ачык Wi-Fi тармагы жеткиликтүү</item>
+ <item quantity="one">Ачык Wi-Fi тармагы жеткиликтүү</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi түйүнүнө кирүү"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"түйүнгө кирүү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1808,6 +1782,7 @@
<skip />
<!-- no translation found for usb_ptp_notification_title (1960817192216064833) -->
<skip />
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI түзмөк катары туташкан"</string>
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB аксессуарга байланышты"</string>
@@ -1978,8 +1953,10 @@
<skip />
<!-- no translation found for find_on_page (1946799233822820384) -->
<skip />
- <!-- no translation found for matches_found:one (8167147081136579439) -->
- <!-- no translation found for matches_found:other (4641872797067609177) -->
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> ичинен <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1 дал келүү</item>
+ </plurals>
<!-- no translation found for action_mode_done (7217581640461922289) -->
<skip />
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB сактагыч чыгарылууда…"</string>
@@ -2301,10 +2278,10 @@
<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_too_short" msgid="8173982756265777792">"PIN өтө кыска. Аз дегенде 4 сандан турушу керек."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 секундадан кийин кайталаңыз"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> секундадан кийин кайталаңыз"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунддан кийин кайталаңыз</item>
+ <item quantity="one">1 секунддан кийин кайталаңыз</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Кийинчерээк кайталаңыз"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Толук экран абалынан чыгуу үчүн жогорудан төмөн сүрүңүз."</string>
<string name="done_label" msgid="2093726099505892398">"Даяр"</string>
@@ -2330,22 +2307,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Батареянын өмүрүн узартуу үчүн, батареяны үнөмдөгүч түзмөгүңүздүн ишинин майнаптуулугун азайтып, дирилдөө, жайгашкан жерди аныктоо кызматтары жана фондук дайындардын көпчүлүгүн чектеп коёт. Электрондук почта, билдирүү жазышуу жана башка шайкештештирүүгө байланыштуу колдонмолор ачылмайынча жаңыртылбай калышы мүмкүн.\n\nБатарея үнөмдөгүч түзмөгүңүз кубатталып жатканда автоматтык түрдө өчүп калат."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Иштебей турган абал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> аяктамайынча"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Аракетсиз убакытыңыз бүткүчө"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Бир мүнөткө (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> чейин)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d мүнөткө (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> чейин)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Бир саатка (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> чейин)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d саатка (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> чейин)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Бир мүнөткө"</item>
- <item quantity="other" msgid="6924190729213550991">"%d мүнөткө"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Бир саатка"</item>
- <item quantity="other" msgid="5408537517529822157">"%d саатка"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d мүнөткө (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> чейин)</item>
+ <item quantity="one">Бир мүнөткө (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> чейин)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d саатка (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> чейин)</item>
+ <item quantity="one">Бир саатка (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> чейин)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d мүнөткө</item>
+ <item quantity="one">Бир мүнөткө</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d саатка</item>
+ <item quantity="one">Бир саатка</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> чейин"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Белгисиз"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Жыйнап коюу"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 086a9e5..fa546f2 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ຊິມກາດຂອງທ່ານຖືກລັອກດ້ວຍລະຫັດ PUK. ໃຫ້ພິມລະຫັດ PUK ເພື່ອປົດລັອກມັນ."</string>
<string name="needPuk2" msgid="4526033371987193070">"ພິມ PUK2 ເພື່ອປົດລັອກ SIM card."</string>
<string name="enablePin" msgid="209412020907207950">"ບໍ່ສຳເລັດ, ເປີດນໍາໃຊ້ການລັອກຂອງ SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະຖືກລັອກ."</item>
- <item quantity="other" msgid="7530597808358774740">"ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະຖືກລັອກ."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະຖືກລັອກ.</item>
+ <item quantity="one">ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະຖືກລັອກ.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ໝາຍເລກຜູ່ໂທເຂົ້າ"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 ວິນາທີກ່ອນ"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> ວິນາທີກ່ອນໜ້ານີ້"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 ນາທີກ່ອນໜ້ານີ້"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> ນາທີທີ່ຜ່ານມາ"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ຊົ່ວໂມງກ່ອນໜ້ານີ້"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງທີ່ຜ່ານມາ"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ວັນສຸດທ້າຍ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ວັນສຸດທ້າຍ</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"ເດືອນແລ້ວ"</string>
<string name="older" msgid="5211975022815554840">"ເກົ່າກວ່າ"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ມື້ວານນີ້"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> ມື້ກ່ອນ"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"ໃນອີກ 1 ວິນາທີ"</item>
- <item quantity="other" msgid="1241926116443974687">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ວິນາທີ"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"ໃນ 1 ນາທີ"</item>
- <item quantity="other" msgid="3330713936399448749">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ນາທີ"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"ໃນ 1 ຊົ່ວໂມງ"</item>
- <item quantity="other" msgid="547290677353727389">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງ"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ມື້ອື່ນ"</item>
- <item quantity="other" msgid="5109449375100953247">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ມື້"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 ວິນາທີກ່ອນ"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> ວິ ກ່ອນໜ້ານີ້"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 ນທ ກ່ອນ"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> ນທ ກ່ອນໜ້ານີ້"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ຊົ່ວໂມງກ່ອນ"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງກ່ອນໜ້ານີ້"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ມື້ວານນີ້"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> ມື້ກ່ອນໜ້ານີ້"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"ໃນ 1 ວິ"</item>
- <item quantity="other" msgid="5495880108825805108">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ວິ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"ໃນ 1 ນາທີ"</item>
- <item quantity="other" msgid="4216113292706568726">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ນທ"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ໃນ 1 ຊົ່ວໂມງ"</item>
- <item quantity="other" msgid="3705373766798013406">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງ"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ມື້ອື່ນ"</item>
- <item quantity="other" msgid="2973062968038355991">"ໃນ <xliff:g id="COUNT">%d</xliff:g> ມື້"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"ວັນທີ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ເວລາ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ໃນ <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"ອາທິດ"</string>
<string name="year" msgid="4001118221013892076">"ປີ"</string>
<string name="years" msgid="6881577717993213522">"ປິ"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 ວິນາທີ"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ວິນາທີ"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 ນາທີ"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> ນາທີ"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ຊົ່ວໂມງ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງ"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ວິນາທີ</item>
+ <item quantity="one">1ວິນາທີ</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ນາທີ</item>
+ <item quantity="one">1 ນາທີ</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ຊົ່ວໂມງ</item>
+ <item quantity="one">1 ຊົ່ວໂມງ</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ບໍ່ມີ"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ຣິງໂທນ"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"ຣິງໂທນທີ່ບໍ່ຮູ້ຈັກ"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"ເຄືອຂ່າຍ Wi-Fi ທີ່ພົບ"</item>
- <item quantity="other" msgid="4192424489168397386">"ມີເຄືອຂ່າຍ Wi-Fi ໃຫ້ໃຊ້"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"ເປີດ Wi-Fi ເຄືອຂ່າຍທີ່ມີ"</item>
- <item quantity="other" msgid="7915895323644292768">"ເຄືອຂ່າຍ Wi-Fi ແບບເປີດທີ່ພົບ"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
+ <item quantity="one">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
+ <item quantity="one">ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ຕົກລົງ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"ເຊື່ອມຕໍ່ເປັນອຸປະກອນສື່"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"ເຊື່ອມຕໍ່ເປັນກ້ອງຖ່າຍຮູບແລ້ວ"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"ເຊື່ອມຕໍ່ເປັນອຸປະກອນ MIDI ແລ້ວ"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ເຊື່ອມຕໍ່ໃນນາມຕົວຕິດຕັ້ງ"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ເຊື່ອມຕໍ່ກັບອຸປະກອນເສີມ USB ແລ້ວ"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"ແຕະເພື່ອເບິ່ງໂຕເລືອກເລືອກ USB ອື່ນໆ."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 ກົງກັນ"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ຈາກທັງໝົດ <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> ໃນ <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 ກົງກັນ</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"ແລ້ວໆ"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"ກຳລັງຖອນການເຊື່ອມຕໍ່ບ່ອນຈັດເກັບຂໍ້ມູນ USB …"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"ຖອນການເຊື່ອມຕໍ່ SD card..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN ສັ້ນເກີນໄປ. ຕ້ອງມີຢ່າງໜ້ອຍ 4 ຫຼັກ."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"ລອງໃໝ່ໃນອີກ 1 ວິນາທີ"</item>
- <item quantity="other" msgid="4730868920742952817">"ລອງໃໝ່ໃນອີກ <xliff:g id="COUNT">%d</xliff:g> ວິນາທີ"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">ລອງໃໝ່ໃນອີກ <xliff:g id="COUNT">%d</xliff:g> ລອງໃໝ່ໃນອີກ 1 ວິນາທີ</item>
+ <item quantity="one">ລອງໃໝ່ໃນອີກ 1 ວິນາທີ</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ລອງໃໝ່ອີກຄັ້ງໃນພາຍຫລັງ."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"ປັດລົງມາຈາກທາງເທິງເພື່ອອອກຈາກໂໝດເຕັມໜ້າຈໍ."</string>
<string name="done_label" msgid="2093726099505892398">"ແລ້ວໆ"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ເພື່ອຊ່ວຍເພີ່ມອາຍຸແບັດເຕີຣີ, ຕົວປະຢັດໄຟແບັດເຕີຣີຫຼຸດປະສິດທິພາບການເຮັດວຽກຂອງອຸປະກອນຂອງທ່ານລົງ ແລະຈຳກັດການສັ່ນ, ການບໍລິການຫາທີ່ຕັ້ງ, ແລະຂໍ້ມູນພື້ນຫຼັງເກືອບທັງໝົດ. ອີເມວ, ການສົ່ງຂໍ້ຄວາມ, ແລະແອັບອື່ນໆທີ່ອາໄສການຊິງຄ໌ອາດຈະບໍ່ອັບເດດ ນອກຈາກວ່າທ່ານເປີດມັນ.\n\nຕົວປະຢັດໄຟແບັດເຕີຣີຈະປິດອັດຕະໂນມັດ ເມື່ອອຸປະກອນຂອງທ່ານກຳລັງສາກຢູ່."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ຈົນກວ່າດາວທາມຂອງທ່ານຈະສິ້ນສຸດທີ່ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"ຈົນກວ່າເວລາປິດເຮັດວຽກຂອງທ່ານສິ້ນສຸດລົງ"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ເປັນເວລາ 1 ນາທີ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"ເປັນເວລາ %1$d ນາທີ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ເປັນເວລາ 1 ຊົ່ວໂມງ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"ເປັນເວລາ %1$d ຊົ່ວໂມງ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ເປັນເວລານຶ່ງນາທີ"</item>
- <item quantity="other" msgid="6924190729213550991">"ເປັນເວລາ %d ນາທີ"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ເປັນເວລານຶ່ງຊົ່ວໂມງ"</item>
- <item quantity="other" msgid="5408537517529822157">"ເປັນເວລາ %d ຊົ່ວໂມງ"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">ເປັນເວລາ %1$d ນາທີ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">ເປັນເວລາ 1 ນາທີ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">ເປັນເວລາ %1$d ຊົ່ວໂມງ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">ເປັນເວລາ 1 ຊົ່ວໂມງ (ຈົນຮອດ <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">ເປັນເວລາ %d ນາທີ</item>
+ <item quantity="one">ເປັນເວລາໜຶ່ງນາທີ</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">ເປັນເວລາ %d ຊົ່ວໂມງ</item>
+ <item quantity="one">ເປັນເວລາໜຶ່ງຊົ່ວໂມງ</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"ຢ່າງບໍ່ມີກຳນົດ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ຫຍໍ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d7a93ac..590e9ea 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"Jūsų SIM kortelė yra užrakinta PUK kodu. Jei norite ją atrakinti, įveskite PUK kodą."</string>
<string name="needPuk2" msgid="4526033371987193070">"Įveskite PUK2 kodą, kad panaikintumėte SIM kortelės blokavimą."</string>
<string name="enablePin" msgid="209412020907207950">"Nepavyko. Įgalinti SIM / RUIM užraktą."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Liko <xliff:g id="NUMBER">%d</xliff:g> band. Paskui SIM kortelė bus užrakinta."</item>
- <item quantity="other" msgid="7530597808358774740">"Liko <xliff:g id="NUMBER">%d</xliff:g> band. Paskui SIM kortelė bus užrakinta."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymas. Tada SIM kortelė bus užrakinta.</item>
+ <item quantity="few">Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymai. Tada SIM kortelė bus užrakinta.</item>
+ <item quantity="many">Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymo. Tada SIM kortelė bus užrakinta.</item>
+ <item quantity="other">Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymų. Tada SIM kortelė bus užrakinta.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Įeinančio skambintojo ID"</string>
@@ -1131,73 +1133,14 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"„<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>“ nori įgalinti naršymą liečiant. Kai naršymas liečiant bus įjungtas, galėsite išgirsti ar peržiūrėti pirštu liečiamų elementų aprašus arba atlikdami gestus naudoti telefoną."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Prieš 1 mėn."</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Prieš maždaug 1 mėnesį"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Prieš 1 sek."</item>
- <item quantity="other" msgid="3903706804349556379">"Prieš <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Prieš 1 minutę"</item>
- <item quantity="other" msgid="2176942008915455116">"Prieš <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Prieš 1 valandą"</item>
- <item quantity="other" msgid="2467273239587587569">"Prieš <xliff:g id="COUNT">%d</xliff:g> val."</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> pastaroji diena</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> pastarosios dienos</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> pastarosios dienos</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> pastarųjų dienų</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Paskutinį mėnesį"</string>
<string name="older" msgid="5211975022815554840">"Senesni"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"vakar"</item>
- <item quantity="other" msgid="2479586466153314633">"Prieš <xliff:g id="COUNT">%d</xliff:g> d."</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"po 1 sek."</item>
- <item quantity="other" msgid="1241926116443974687">"po <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"po 1 min."</item>
- <item quantity="other" msgid="3330713936399448749">"po <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"po 1 val."</item>
- <item quantity="other" msgid="547290677353727389">"po <xliff:g id="COUNT">%d</xliff:g> val."</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"rytoj"</item>
- <item quantity="other" msgid="5109449375100953247">"po <xliff:g id="COUNT">%d</xliff:g> d."</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Prieš 1 sek."</item>
- <item quantity="other" msgid="3699169366650930415">"Prieš <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Prieš 1 min."</item>
- <item quantity="other" msgid="851164968597150710">"Prieš <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Prieš 1 valandą"</item>
- <item quantity="other" msgid="6889970745748538901">"Prieš <xliff:g id="COUNT">%d</xliff:g> val."</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"vakar"</item>
- <item quantity="other" msgid="3453342639616481191">"Prieš <xliff:g id="COUNT">%d</xliff:g> d."</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"po 1 sek."</item>
- <item quantity="other" msgid="5495880108825805108">"po <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"po 1 min."</item>
- <item quantity="other" msgid="4216113292706568726">"po <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"po 1 val."</item>
- <item quantity="other" msgid="3705373766798013406">"po <xliff:g id="COUNT">%d</xliff:g> val."</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"rytoj"</item>
- <item quantity="other" msgid="2973062968038355991">"po <xliff:g id="COUNT">%d</xliff:g> d."</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> m."</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"sav."</string>
<string name="year" msgid="4001118221013892076">"metai"</string>
<string name="years" msgid="6881577717993213522">"metai"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sek."</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 min."</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 val."</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> val."</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekundė</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekundės</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> sekundės</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekundžių</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minutė</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minutės</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> minutės</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minučių</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> valanda</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> valandos</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> valandos</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> valandų</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Vaizdo įrašo problema"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis vaizdo įrašas netinkamas srautiniu būdu perduoti į šį įrenginį."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Negalima paleisti šio vaizdo įrašo."</string>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nežinomas skambėjimo tonas"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Galimas „Wi-Fi“ tinklas"</item>
- <item quantity="other" msgid="4192424489168397386">"galimi „Wi-Fi“ tinklai"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Atidaryti galimą „Wi-Fi“ tinklą"</item>
- <item quantity="other" msgid="7915895323644292768">"Atidaryti galimus „Wi-Fi“ tinklus"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Pasiekiami „Wi-Fi“ tinklai</item>
+ <item quantity="few">Pasiekiami „Wi-Fi“ tinklai</item>
+ <item quantity="many">Pasiekiami „Wi-Fi“ tinklai</item>
+ <item quantity="other">Pasiekiami „Wi-Fi“ tinklai</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
+ <item quantity="few">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
+ <item quantity="many">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
+ <item quantity="other">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Prisijungti prie „Wi-Fi“ ryšio tinklo"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Prisijungti prie tinklo"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Gerai"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Prij. kaip medijos įrenginys"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Prij. kaip fotoap."</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Prijungtas kaip MIDI įrenginys"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Prij. kaip diegimo programa"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Prijungta prie USB priedo"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Jei norite matyti kitas USB parinktis, palieskite."</string>
@@ -1531,10 +1485,12 @@
<string name="skip_button_label" msgid="1275362299471631819">"Praleisti"</string>
<string name="no_matches" msgid="8129421908915840737">"Nėra atitikčių"</string>
<string name="find_on_page" msgid="1946799233822820384">"Ieškoti puslapyje"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 atitiktis"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Atlikta"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Pašalinama USB atmintis..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Pašalinama SD kortelė..."</string>
@@ -1820,10 +1776,12 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Sukurti modifikavimo apribojimų PIN kodą"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN kodas neatitinka. Bandykite dar kartą."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN kodas per trumpas. Jis turi būti bent 4 skaitmenų."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Band. dar po 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Band. dar po <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Bandykite dar kartą po <xliff:g id="COUNT">%d</xliff:g> sekundės</item>
+ <item quantity="few">Bandykite dar kartą po <xliff:g id="COUNT">%d</xliff:g> sekundžių</item>
+ <item quantity="many">Bandykite dar kartą po <xliff:g id="COUNT">%d</xliff:g> sekundės</item>
+ <item quantity="other">Bandykite dar kartą po <xliff:g id="COUNT">%d</xliff:g> sekundžių</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Vėliau bandykite dar kartą"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Perbraukite nuo viršaus žemyn, kad išeitumėte iš viso ekrano režimo"</string>
<string name="done_label" msgid="2093726099505892398">"Atlikta"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Kad tausotų akumuliatoriaus energiją akumuliatoriaus tausojimo priemonė sumažina įrenginio veikimą ir apriboja vibravimą, vietovės paslaugas bei daugumą foninių duomenų. El. pašto, susirašinėjimo žinutėmis ir kitos programos, kurios veikia sinchronizavimo pagrindu, gali būti neatnaujintos, nebent jas atidarysite.\n\nAkumuliatoriaus tausojimo priemonė automatiškai išjungiama, kai įrenginys įkraunamas."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kol jūsų prastova baigsis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Kol baigsis prastova"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Vieną minutę (iki <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d min. (iki <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Vieną valandą (iki <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d val. (iki <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 min."</item>
- <item quantity="other" msgid="6924190729213550991">"%d min."</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 val."</item>
- <item quantity="other" msgid="5408537517529822157">"%d val."</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d minutę (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d minutes (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d minutės (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d minučių (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d valandą (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d valandas (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d valandos (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d valandų (iki <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d minutę</item>
+ <item quantity="few">%d minutes</item>
+ <item quantity="many">%d minutės</item>
+ <item quantity="other">%d minučių</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d valandą</item>
+ <item quantity="few">%d valandas</item>
+ <item quantity="many">%d valandos</item>
+ <item quantity="other">%d valandų</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Neapibrėžta"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Sutraukti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1989b55..e6a27a1 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -61,10 +61,11 @@
<string name="needPuk" msgid="919668385956251611">"SIM karte ir bloķēta ar PUK kodu. Ierakstiet PUK kodu, lai to atbloķētu."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ierakstiet PUK2 kodu, lai atbloķētu SIM karti."</string>
<string name="enablePin" msgid="209412020907207950">"Neizdevās. Iespējojiet SIM/RUIM bloķēšanu."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi, pirms SIM karte tiks bloķēta."</item>
- <item quantity="other" msgid="7530597808358774740">"Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi(-es), pirms SIM karte tiks bloķēta."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="zero">Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes. Pēdējā mēģinājuma kļūdas gadījumā SIM karte tiks bloķēta.</item>
+ <item quantity="one">Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizi. Pēdējā mēģinājuma kļūdas gadījumā SIM karte tiks bloķēta.</item>
+ <item quantity="other">Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes. Pēdējā mēģinājuma kļūdas gadījumā SIM karte tiks bloķēta.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Ienākošā zvana zvanītāja ID"</string>
@@ -1131,73 +1132,13 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vēlas iespējot funkciju “Atklāt pieskaroties”. Kad ir ieslēgta funkcija “Atklāt pieskaroties”, var dzirdēt vai redzēt tā vienuma aprakstu, virs kura atrodas pirksts, vai veikt žestus, lai mijiedarbotos ar tālruni."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Pirms 1 mēneša"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vairāk nekā pirms 1 mēneša"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Pirms 1 sekundes"</item>
- <item quantity="other" msgid="3903706804349556379">"Pirms <xliff:g id="COUNT">%d</xliff:g> sekundes(-ēm)"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Pirms 1 minūtes"</item>
- <item quantity="other" msgid="2176942008915455116">"Pirms <xliff:g id="COUNT">%d</xliff:g> minūtes(-ēm)"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Pirms 1 stundas"</item>
- <item quantity="other" msgid="2467273239587587569">"Pirms <xliff:g id="COUNT">%d</xliff:g> stundas(-ām)"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="zero">Pēdējās <xliff:g id="COUNT_1">%d</xliff:g> dienās</item>
+ <item quantity="one">Pēdējā <xliff:g id="COUNT_1">%d</xliff:g> dienā</item>
+ <item quantity="other">Pēdējās <xliff:g id="COUNT_1">%d</xliff:g> dienās</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Iepriekšējā mēnesī"</string>
<string name="older" msgid="5211975022815554840">"Vecāks"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"vakar"</item>
- <item quantity="other" msgid="2479586466153314633">"Pirms <xliff:g id="COUNT">%d</xliff:g> dienas(-ām)"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"pēc 1 sekundes"</item>
- <item quantity="other" msgid="1241926116443974687">"pēc <xliff:g id="COUNT">%d</xliff:g> sekundes(-ēm)"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"pēc 1 minūtes"</item>
- <item quantity="other" msgid="3330713936399448749">"pēc <xliff:g id="COUNT">%d</xliff:g> minūtes(-ēm)"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"pēc 1 stundas"</item>
- <item quantity="other" msgid="547290677353727389">"pēc <xliff:g id="COUNT">%d</xliff:g> stundas(-ām)"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"rītdien"</item>
- <item quantity="other" msgid="5109449375100953247">"pēc <xliff:g id="COUNT">%d</xliff:g> dienas(-ām)"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Pirms 1 sekundes"</item>
- <item quantity="other" msgid="3699169366650930415">"Pirms <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Pirms 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"Pirms <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Pirms 1 stundas"</item>
- <item quantity="other" msgid="6889970745748538901">"Pirms <xliff:g id="COUNT">%d</xliff:g> stundas(-ām)"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"vakar"</item>
- <item quantity="other" msgid="3453342639616481191">"Pirms <xliff:g id="COUNT">%d</xliff:g> dienas(-ām)"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"pēc 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"pēc <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"pēc 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"pēc <xliff:g id="COUNT">%d</xliff:g> minūtes(-ēm)"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"pēc 1 stundas"</item>
- <item quantity="other" msgid="3705373766798013406">"pēc <xliff:g id="COUNT">%d</xliff:g> stundas(-ām)"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"rītdien"</item>
- <item quantity="other" msgid="2973062968038355991">"pēc <xliff:g id="COUNT">%d</xliff:g> dienas(-ām)"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"šādā datumā: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"šādā gadā: <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1154,21 @@
<string name="weeks" msgid="6509623834583944518">"nedēļas"</string>
<string name="year" msgid="4001118221013892076">"gads"</string>
<string name="years" msgid="6881577717993213522">"gadi"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 s"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 min"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 stunda"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> sekunžu</item>
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekundes</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekundes</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> minūšu</item>
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minūte</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minūtes</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="zero"><xliff:g id="COUNT">%d</xliff:g> stundu</item>
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> stunda</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> stundas</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video problēma"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Šis video nav derīgs straumēšanai uz šo ierīci."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nevar atskaņot šo video."</string>
@@ -1333,14 +1277,16 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nav"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zvana signāli"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nezināms zvana signāls"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi tīkls ir pieejams."</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi tīkli ir pieejami"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Ir pieejams atvērts Wi-Fi tīkls"</item>
- <item quantity="other" msgid="7915895323644292768">"Ir pieejami atvērti Wi-Fi tīkli."</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="zero">Pieejami Wi-Fi tīkli</item>
+ <item quantity="one">Pieejami Wi-Fi tīkli</item>
+ <item quantity="other">Pieejami Wi-Fi tīkli</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="zero">Ir pieejami atvērti Wi-Fi tīkli</item>
+ <item quantity="one">Ir pieejami atvērti Wi-Fi tīkli</item>
+ <item quantity="other">Ir pieejami atvērti Wi-Fi tīkli</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Pierakstieties Wi-Fi tīklā."</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Pierakstīšanās tīklā"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1362,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Labi"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pievienots kā multivides ierīce"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pievienots kā kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Ierīce tika pievienota kā MIDI ierīce."</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pievienots kā instalēšanas programma"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ir izveidots savienojums ar USB piederumu."</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Pieskarieties, lai skatītu citas USB opcijas."</string>
@@ -1531,10 +1478,11 @@
<string name="skip_button_label" msgid="1275362299471631819">"Izlaist"</string>
<string name="no_matches" msgid="8129421908915840737">"Nav atbilstību"</string>
<string name="find_on_page" msgid="1946799233822820384">"Atrast lapā"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 atbilstība"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> no <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="zero"><xliff:g id="INDEX">%d</xliff:g>. no <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g>. no <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>. no <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Gatavs"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Notiek USB atmiņas atvienošana..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Notiek SD kartes atvienošana..."</string>
@@ -1820,10 +1768,11 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Izveidojiet PIN, lai mainītu ierobežojumus."</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Ievadītie PIN neatbilst. Mēģiniet vēlreiz."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ir pārāk īss. Tam ir jābūt vismaz 4 ciparus garam."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Mēģ. vēl pēc 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Mēģ. vēl pēc <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="zero">Mēģiniet vēlreiz pēc <xliff:g id="COUNT">%d</xliff:g> sekundēm</item>
+ <item quantity="one">Mēģiniet vēlreiz pēc <xliff:g id="COUNT">%d</xliff:g> sekundes</item>
+ <item quantity="other">Mēģiniet vēlreiz pēc <xliff:g id="COUNT">%d</xliff:g> sekundēm</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Vēlāk mēģiniet vēlreiz."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Lai izietu no pilnekrāna režīma, velciet no augšas uz leju."</string>
<string name="done_label" msgid="2093726099505892398">"Gatavs"</string>
@@ -1849,22 +1798,26 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Lai paildzinātu akumulatora darbību, akumulatora jaudas taupīšanas režīmā tiek samazināta ierīces veiktspēja un tiek ierobežota vibrācija, atrašanās vietu pakalpojumi un lielākā daļa fona datu. E-pasta, ziņojumapmaiņas un cita veida lietotnes, kuru darbības pamatā ir datu sinhronizācija, var netikt atjauninātas, ja tās neatverat.\n\nTiklīdz tiek sākta ierīces uzlāde, akumulatora jaudas taupīšanas režīms automātiski tiek izslēgts."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Līdz beigsies dīkstāve (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Līdz beidzas dīkstāve"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Vienu minūti (līdz <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d minūtes (līdz <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Vienu stundu (līdz <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d stundas (līdz <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Vienu minūti"</item>
- <item quantity="other" msgid="6924190729213550991">"%d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Vienu stundu"</item>
- <item quantity="other" msgid="5408537517529822157">"%d h"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="zero">%1$d minūtes (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">%1$d minūti (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d minūtes (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="zero">%1$d stundas (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">%1$d stundu (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d stundas (līdz <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="zero">%d minūtes</item>
+ <item quantity="one">%d minūti</item>
+ <item quantity="other">%d minūtes</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="zero">%d stundas</item>
+ <item quantity="one">%d stundu</item>
+ <item quantity="other">%d stundas</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Līdz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Uz nenoteiktu laiku"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Sakļaut"</string>
diff --git a/core/res/res/values-mcc259-mnc05/config.xml b/core/res/res/values-mcc259-mnc05/config.xml
new file mode 100644
index 0000000..065668c
--- /dev/null
+++ b/core/res/res/values-mcc259-mnc05/config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The list of ril radio technologies (see ServiceState.java) which only support
+ a single data connection at one time. This may change by carrier via
+ overlays (some don't support multiple pdp on UMTS). All unlisted radio
+ tech types support unlimited types (practically only 2-4 used). -->
+ <integer-array name="config_onlySingleDcAllowed">
+ <item>1</item> <!-- GPRS -->
+ <item>2</item> <!-- EDGE -->
+ <item>3</item> <!-- UMTS -->
+ <item>9</item> <!-- HSDPA -->
+ <item>10</item> <!-- HSUPA -->
+ <item>11</item> <!-- HSPA -->
+ <item>14</item> <!-- LTE -->
+ <item>15</item> <!-- HSPAP -->
+ </integer-array>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a3d0386..5f89553 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Вашата СИМ картичка е заклучена со ПУК код. Внесете го ПУК кодот за да се отклучи."</string>
<string name="needPuk2" msgid="4526033371987193070">"Внесете го ПУК2 кодот за да се одблокира СИМ картичката."</string>
<string name="enablePin" msgid="209412020907207950">"Неуспешно, овозможи заклучување на SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Ви преостанува уште <xliff:g id="NUMBER">%d</xliff:g> обид, а потоа СИМ картичката ќе се заклучи."</item>
- <item quantity="other" msgid="7530597808358774740">"Ви преостануваат уште <xliff:g id="NUMBER">%d</xliff:g> обиди, а потоа СИМ картичката ќе се заклучи."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ИД на дојдовен повикувач"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"пред 1 секунда"</item>
- <item quantity="other" msgid="3903706804349556379">"пред <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"пред 1 минута"</item>
- <item quantity="other" msgid="2176942008915455116">"пред <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Пред 1 час"</item>
- <item quantity="other" msgid="2467273239587587569">"пред <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Последните <xliff:g id="COUNT_1">%d</xliff:g> ден</item>
+ <item quantity="other">Последните <xliff:g id="COUNT_1">%d</xliff:g> дена</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Минатиот месец"</string>
<string name="older" msgid="5211975022815554840">"Постари"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"вчера"</item>
- <item quantity="other" msgid="2479586466153314633">"Пред <xliff:g id="COUNT">%d</xliff:g> дена"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"за 1 секунда"</item>
- <item quantity="other" msgid="1241926116443974687">"за <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"за 1 минута"</item>
- <item quantity="other" msgid="3330713936399448749">"за <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"за 1 час"</item>
- <item quantity="other" msgid="547290677353727389">"за <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"утре"</item>
- <item quantity="other" msgid="5109449375100953247">"за <xliff:g id="COUNT">%d</xliff:g> дена"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"пред 1 сек"</item>
- <item quantity="other" msgid="3699169366650930415">"пред <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"пред 1 мин"</item>
- <item quantity="other" msgid="851164968597150710">"пред <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"пред 1 час"</item>
- <item quantity="other" msgid="6889970745748538901">"пред <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"вчера"</item>
- <item quantity="other" msgid="3453342639616481191">"Пред <xliff:g id="COUNT">%d</xliff:g> дена"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"за 1 сек"</item>
- <item quantity="other" msgid="5495880108825805108">"за <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"за 1 мин"</item>
- <item quantity="other" msgid="4216113292706568726">"за <xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"за 1 час"</item>
- <item quantity="other" msgid="3705373766798013406">"за <xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"утре"</item>
- <item quantity="other" msgid="2973062968038355991">"за <xliff:g id="COUNT">%d</xliff:g> дена"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"на <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"во <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"во <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"седмици"</string>
<string name="year" msgid="4001118221013892076">"година"</string>
<string name="years" msgid="6881577717993213522">"години"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 минута"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минути"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 час"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> часа"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> секунда</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> минута</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минути</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> час</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ниедна"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Непозната мелодија"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi мрежа е достапна"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi мрежи се достапни"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Отворена Wi-Fi мрежа е достапна"</item>
- <item quantity="other" msgid="7915895323644292768">"Отворени Wi-Fi мрежи се достапни"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Wi-Fi мрежи се достапни</item>
+ <item quantity="other">Wi-Fi мрежи се достапни</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Отворени Wi-Fi мрежи се достапни</item>
+ <item quantity="other">Отворени Wi-Fi мрежи се достапни</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Пријави се на Wi-Fi мрежа"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Пријави се на мрежа"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Во ред"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Поврзан како уред за медиуми"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Поврзан како фотоапарат"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Поврзан како уред со MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Поврзан како инсталатор"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Поврзан со УСБ додаток"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Допри за други опции на УСБ."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 совпаѓање"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Одмонтирање УСБ меморија..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Одмонтирање СД картичка..."</string>
@@ -1822,10 +1762,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Создади ПИН за измена на ограничувањата"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"ПИН кодовите не се совпаѓаат. Обиди се повторно."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"ПИН кодот е премногу краток. Мора да има најмалку 4 цифри."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Обидете се повторно за 1 секунда"</item>
- <item quantity="other" msgid="4730868920742952817">"Обидете се повторно за <xliff:g id="COUNT">%d</xliff:g> секунди"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Обидете се повторно по <xliff:g id="COUNT">%d</xliff:g> секунда</item>
+ <item quantity="other">Обидете се повторно по <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Обиди се повторно подоцна"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Помини со прстот одозгора надолу да излезе од режим на цел екран."</string>
<string name="done_label" msgid="2093726099505892398">"Готово"</string>
@@ -1851,22 +1791,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"За да ви помогне да ја подобрите трајноста на батеријата, штедачот на батеријата ја намалува изведбата на уредот и го ограничува вибрирањето, услугите за локација и повеќето податоци од заднина. Е-поштата, испраќањето пораки и другите апликации кои се потпираат на синхронизација можеби нема да се ажурираат доколку не ги отворите.\n\nШтедачот на батеријата автоматски се исклучува кога уредот се полни."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Додека не заврши паузата во <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Додека да заврши паузата"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Една минута (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d минути (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Еден час (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d часа (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"За една минута"</item>
- <item quantity="other" msgid="6924190729213550991">"За %d минути"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"За еден час"</item>
- <item quantity="other" msgid="5408537517529822157">"За %d часа"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">За %1$d минута (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">За %1$d минути (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">За %1$d час (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">За %1$d часа (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">За %d минута</item>
+ <item quantity="other">За %d минути</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">За % d час</item>
+ <item quantity="other">За % d часа</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Неодредено време"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Собери"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 49f86e8..d9286eb 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"നിങ്ങളുടെ സിം കാർഡ് PUK ലോക്ക് ചെയ്തതാണ്. ഇത് അൺലോക്ക് ചെയ്യാൻ PUK കോഡ് ടൈപ്പുചെയ്യുക."</string>
<string name="needPuk2" msgid="4526033371987193070">"സിം കാർഡ് തടഞ്ഞത് മാറ്റാൻ PUK2 ടൈപ്പുചെയ്യുക."</string>
<string name="enablePin" msgid="209412020907207950">"വിജയകരമല്ല, സിം/RUIM ലോക്ക് പ്രവർത്തനക്ഷമമാക്കുക."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"സിം ലോക്കാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമം കൂടി ബാക്കിയുണ്ട്."</item>
- <item quantity="other" msgid="7530597808358774740">"സിം ലോക്കാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ബാക്കിയുണ്ട്."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">SIM ലോക്കാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു.</item>
+ <item quantity="one">SIM ലോക്കാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ഇൻകമിംഗ് കോളർ ഐഡി"</string>
@@ -1131,73 +1131,12 @@
<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">"ഒരു മാസം മുമ്പ്"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 നിമിഷം മുമ്പ്"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> നിമിഷം മുമ്പ്"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 മിനിറ്റ് മുമ്പ്"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> മിനിറ്റ് മുമ്പ്"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 മണിക്കൂര് മുമ്പ്"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂർ മുമ്പ്"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">അവസാന <xliff:g id="COUNT_1">%d</xliff:g> ദിവസം</item>
+ <item quantity="one">അവസാന <xliff:g id="COUNT_0">%d</xliff:g> ദിവസം</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"കഴിഞ്ഞ മാസം"</string>
<string name="older" msgid="5211975022815554840">"പഴയത്"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ഇന്നലെ"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> ദിവസം മുമ്പ്"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"ഒരു നിമിഷത്തിനുള്ളിൽ"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> നിമിഷത്തിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"ഒരു മിനിറ്റിൽ"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> മിനിറ്റിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"ഒരു മണിക്കൂറിനുള്ളിൽ"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂറിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"നാളെ"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> ദിവസത്തിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"ഒരു നിമിഷം മുമ്പ്"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> നിമിഷം മുമ്പ്"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"ഒരു മിനിറ്റ് മുമ്പ്"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> മിനിറ്റ് മുമ്പ്"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 മണിക്കൂര് മുമ്പ്"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂർ മുമ്പ്"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ഇന്നലെ"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> ദിവസം മുമ്പ്"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"ഒരു നിമിഷത്തിനുള്ളിൽ"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> നിമിഷത്തിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"ഒരു മിനിറ്റിനുള്ളിൽ"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> മിനിറ്റിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ഒരു മണിക്കൂറിനുള്ളിൽ"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂറിനുള്ളിൽ"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"നാളെ"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> ദിവസത്തിനുള്ളിൽ"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>-ന്"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>-ൽ"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"ആഴ്ച"</string>
<string name="year" msgid="4001118221013892076">"വര്ഷം"</string>
<string name="years" msgid="6881577717993213522">"വർഷം"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 സെക്കൻഡ്"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> സെക്കൻഡ്"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"ഒരു മിനിറ്റ്"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> മിനിറ്റ്"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"ഒരു മണിക്കൂർ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> മണിക്കൂർ"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> സെക്കൻഡ്</item>
+ <item quantity="one">ഒരു സെക്കൻഡ്</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> മിനിറ്റ്</item>
+ <item quantity="one">ഒരു മിനിറ്റ്</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> മണിക്കൂർ</item>
+ <item quantity="one">ഒരു മണിക്കൂർ</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ഒന്നുമില്ല"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"റിംഗ്ടോണുകൾ"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"അജ്ഞാത റിംഗ്ടോൺ"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi നെറ്റ്വർക്ക് ലഭ്യമാണ്"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi നെറ്റ്വർക്കുകൾ ലഭ്യമാണ്"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"ലഭ്യമായ Wi-Fi നെറ്റ്വർക്ക് തുറക്കുക"</item>
- <item quantity="other" msgid="7915895323644292768">"ലഭ്യമായ Wi-Fi നെറ്റ്വർക്കുകൾ തുറക്കുക"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi നെറ്റ്വർക്കുകൾ ലഭ്യമാണ്</item>
+ <item quantity="one">Wi-Fi നെറ്റ്വർക്ക് ലഭ്യമാണ്</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">ലഭ്യമായ Wi-Fi നെറ്റ്വർക്കുകൾ തുറക്കുക</item>
+ <item quantity="one">ലഭ്യമായ Wi-Fi നെറ്റ്വർക്ക് തുറക്കുക</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi നെറ്റ്വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"നെറ്റ്വർക്കിൽ സൈൻ ഇൻ ചെയ്യുക"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ശരി"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"മീഡിയ ഉപകരണമായി കണക്റ്റുചെയ്തു"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"ഒരു ക്യാമറയായി കണക്റ്റുചെയ്തു"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI ഉപകരണമായി കണക്റ്റുചെയ്തു"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ഇൻസ്റ്റാളറായി കണക്റ്റുചെയ്തു"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ഒരു USB ആക്സസ്സറി കണക്റ്റുചെയ്തു"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"മറ്റ് USB ഓപ്ഷനുകൾക്കായി സ്പർശിക്കുക."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"ഒരു പൊരുത്തം"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> / <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> / <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">ഒരു പൊരുത്തം</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"പൂർത്തിയായി"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB കാർഡ് അൺമൗണ്ടുചെയ്യുന്നു…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD കാർഡ് അൺമൗണ്ടുചെയ്യുന്നു…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"നിയന്ത്രണങ്ങൾ പരിഷ്ക്കരിക്കാൻ ഒരു പിൻ സൃഷ്ടിക്കുക"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"പിൻ നമ്പറുകൾ പൊരുത്തപ്പെടുന്നില്ല. വീണ്ടും ശ്രമിക്കുക"</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"പിൻ തീരെ ചെറുതാണ്. 4 അക്കമെങ്കിലും ഉണ്ടായിരിക്കണം."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"ഒരു സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക</item>
+ <item quantity="one">ഒരു സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"പൂർണ്ണസ്ക്രീനിൽനിന്നും പുറത്തുകടക്കുന്നതിന് മുകളിൽ നിന്നും താഴേക്ക് സ്വൈപ്പുചെയ്യുക."</string>
<string name="done_label" msgid="2093726099505892398">"പൂർത്തിയാക്കി"</string>
@@ -1849,20 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ബാറ്ററി ആയുസ്സ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുന്നതിന്, ബാറ്ററി സേവർ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെ കുറയ്ക്കുകയും വൈബ്രേഷനെയും മിക്ക പശ്ചാത്തല വിവരത്തെയും പരിമിതപ്പെടുത്തുകയും ചെയ്യുന്നു. ഇമെയിൽ, സന്ദേശമയയ്ക്കൽ, സമന്വയിപ്പിക്കലിനെ ആശ്രയിച്ചുള്ള മറ്റ് അപ്ലിക്കേഷനുകൾ എന്നിവ നിങ്ങൾ തുറക്കുന്നതുവരെ അപ്ഡേറ്റുചെയ്യാനിടയില്ല.\n\nനിങ്ങളുടെ ഉപകരണം ചാർജ്ജുചെയ്യുമ്പോൾ ബാറ്ററി സേവർ സ്വയം ഓഫാകും."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ന് നിങ്ങളുടെ കാലാവധി അവസാനിക്കുന്നതുവരെ"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"പ്രവർത്തനരഹിതമായിരിക്കുന്ന സമയം അവസാനിക്കുന്നതുവരെ"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ഒരു മണിക്കൂർ സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> വരെ)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d മണിക്കൂർ സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> വരെ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ഒരു മിനിറ്റ് ദൈർഘ്യം"</item>
- <item quantity="other" msgid="6924190729213550991">"%d മിനിറ്റ് ദൈർഘ്യം"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ഒരു മണിക്കൂർ ദൈർഘ്യം"</item>
- <item quantity="other" msgid="5408537517529822157">"%d മണിക്കൂർ ദൈർഘ്യം"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d മിനിറ്റ് സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> വരെ)</item>
+ <item quantity="one">ഒരു മിനിറ്റ് സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> വരെ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d മണിക്കൂർ സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> വരെ)</item>
+ <item quantity="one">ഒരു മണിക്കൂർ സമയത്തേക്ക് (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> വരെ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d മിനിറ്റ് സമയത്തേക്ക്</item>
+ <item quantity="one">ഒരു മിനിറ്റ് സമയത്തേക്ക്</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d മണിക്കൂർ സമയത്തേക്ക്</item>
+ <item quantity="one">ഒരു മണിക്കൂർ സമയത്തേക്ക്</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> വരെ"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"അവ്യക്തം"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ചുരുക്കുക"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index e714570..017cf95 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM картны PUK-түгжигдсэн. Тайлах бол PUK кодыг бичнэ үү."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM картын хаалтыг болиулах бол PUK2-г бичнэ үү."</string>
<string name="enablePin" msgid="209412020907207950">"Амжилтгүй боллоо, СИМ/РҮИМ түгжээг идэвхжүүлнэ үү."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдлээ."</item>
- <item quantity="other" msgid="7530597808358774740">"СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдлээ."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
+ <item quantity="one">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Дуудлага хийгчийн ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 секундын өмнө"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> секундын өмнө"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 минутын өмнө"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> минутын өмнө"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 цагийн өмнө"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> цагийн өмнө"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Сүүлийн <xliff:g id="COUNT_1">%d</xliff:g> өдөр</item>
+ <item quantity="one">Сүүлийн <xliff:g id="COUNT_0">%d</xliff:g> өдөр</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Сүүлийн сар"</string>
<string name="older" msgid="5211975022815554840">"Хуучин"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"өчигдөр"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> өдрийн өмнө"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 секундын дараа"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> секундын дараа"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 минутын дараа"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> минутын дараа"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 цагийн дараа"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> цагийн дараа"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"маргааш"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> өдрийн дараа"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 секундын өмнө"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> сек дараа"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 мин өмнө"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> минутын өмнө"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 цагийн өмнө"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> цагийн өмнө"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"өчигдөр"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> өдрийн өмнө"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 сек дараа"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> сек дараа"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 мин дараа"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> минутын дараа"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 цагийн дараа"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> цагийн дараа"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"маргааш"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> өдрийн дараа"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"7 хоног"</string>
<string name="year" msgid="4001118221013892076">"жил"</string>
<string name="years" msgid="6881577717993213522">"жил"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунд"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> секунд"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 минут"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минут"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 цаг"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> цаг"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="one">1 секунд</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минут</item>
+ <item quantity="one">1 минут</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> цаг</item>
+ <item quantity="one">1 цаг</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Алийг нь ч биш"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Хонхны ая"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Үл мэдэгдэх хонхны ая"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi сүлжээ ашиглах боломжтой"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi сүлжээ ашиглах боломжгүй"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Нээллтэй Wi-Fi сүлжээ ашиглах боломжтой"</item>
- <item quantity="other" msgid="7915895323644292768">"Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi сүлжээ ашиглах боломжтой</item>
+ <item quantity="one">Wi-Fi сүлжээ ашиглах боломжтой</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой</item>
+ <item quantity="one">Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Сүлжээнд нэвтрэх"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Тийм"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Медиа төхөөрөмж болон холбогдов"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Камер болгон холбов"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI төхөөрөмж хэлбэрээр холбогдсон байна"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Суулгагч болгон холбогдсон"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB төхөөрөмжид холбогдов"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Бусад USB сонголт хийх бол хүрнэ үү."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 утга"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>-н <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>-н <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1 үр дүн гарч ирсэн байна</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Дуусгах"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB санг салгаж байна…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD картыг салгаж байна…"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN хэт богино байна. Хамгийн багадаа 4 цифртэй байх ёстой."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 секундын дараа дахин оролдоно уу"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> секундын дараа дахин оролдоно уу"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секундын дараа дахин оролдоно уу</item>
+ <item quantity="one">1 секундын дараа дахин оролдоно уу</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Дараа дахин оролдоно уу"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Бүтэн дэлгэцээс гарахын тулд дээрээс нь доош шудрана уу."</string>
<string name="done_label" msgid="2093726099505892398">"Дууссан"</string>
@@ -1849,22 +1789,20 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Батарей хадгалах функц нь таны төхөөрөмжийн цэнэгийг хадгалахын тулд гүйцэтгэлийг багасгаж, чичрэлтийг бууруулж, байршлын үйлчилгээнүүд болон бусад өгөгдлийн хэмжээг багасгадаг юм. И-мэйл, мессеж болон бусад синхрон хийдэг апликейшнүүд дараа дахин нээгдэх хүртлээ автоматаар шинэчлэлт хийхгүй.\n\nМөн батарей хадгалах функц нь таныг төхөөрөмжөө цэнэглэх үед автоматаар унтрах юм."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Таны уйтгартай байдал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-д дуусах хүртэл"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Сул зогсолт дуусах хүртэл"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Нэг минутын турш (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> хүртэл)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d минутын турш (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> хүртэл)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Нэг цагийн турш (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> хүртэл)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d цагийн турш (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> хүртэл)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
- <item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Нэг цагийн турш"</item>
- <item quantity="other" msgid="5408537517529822157">"%d цагийн турш"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other"> %1$d минутын турш ( <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> хүртэл)</item>
+ <item quantity="one">нэг минутын турш (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> хүртэл)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d цагийн турш (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> хүртэл)</item>
+ <item quantity="one">Нэг цагийн турш (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> хүртэл)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d минутын турш</item>
+ <item quantity="one">Нэг минутын турш</item>
+ </plurals>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for zen_mode_duration_hours (3938821308277433854) -->
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> хүртэл"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Тодорхойгүй"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Хумих"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 763c18e..7ce0974 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"आपले सिम कार्ड PUK-लॉक केलेले आहे. ते अनलॉक करण्यासाठी PUK कोड टाइप करा."</string>
<string name="needPuk2" msgid="4526033371987193070">"सिम कार्ड अनावरोधित करण्यासाठी PUK2 टाइप करा."</string>
<string name="enablePin" msgid="209412020907207950">"अयशस्वी, सिम/RUIM लॉक सक्षम करा."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"सिम लॉक होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहे."</item>
- <item quantity="other" msgid="7530597808358774740">"सिम लॉक होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहेत."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <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="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"येणारा कॉलर ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 सेकंदापूर्वी"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> सेकंदांपूर्वी"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 मिनिटापूर्वी"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> मिनिटांपूर्वी"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 तासापूर्वी"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> तासांपूर्वी"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">अंतिम <xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
+ <item quantity="other">अंतिम <xliff:g id="COUNT_1">%d</xliff:g> दिवस</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"अंतिम महिना"</string>
<string name="older" msgid="5211975022815554840">"अधिक जुने"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"काल"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> दिवसांपूर्वी"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 सेकंदात"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> सेकंदांमध्ये"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 मिनिटात"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> मिनिटांमध्ये"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 तासात"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> तासांमध्ये"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"उद्या"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> दिवसांमध्ये"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 सेकंदापूर्वी"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> सेकंदांपूर्वी"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 मिनिटापूर्वी"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> मिनिटांपूर्वी"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 तासापूर्वी"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> तासांपूर्वी"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"काल"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> दिवसांपूर्वी"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 सेकंदामध्ये"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> सेकंदांमध्ये"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 मिनिटामध्ये"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> मिनिटांमध्ये"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 तासात"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> तासांमध्ये"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"उद्या"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> दिवसांमध्ये"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> रोजी"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> वाजता"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> मध्ये"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"आठवडे"</string>
<string name="year" msgid="4001118221013892076">"वर्ष"</string>
<string name="years" msgid="6881577717993213522">"वर्षे"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 सेकंद"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> सेकंद"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 मिनिट"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> मिनिटे"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 तास"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> तास"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंद</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकंद</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> मिनिट</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> मिनिटे</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> तास</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"काहीही नाही"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिंगटोन"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"वाय-फाय नेटवर्क उपलब्ध"</item>
- <item quantity="other" msgid="4192424489168397386">"वाय-फाय नेटवर्क उपलब्ध"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"खुले वाय-फाय नेटवर्क उपलब्ध"</item>
- <item quantity="other" msgid="7915895323644292768">"खुले वाय-फाय नेटवर्क उपलब्ध"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">वाय-फाय नेटवर्क उपलब्ध</item>
+ <item quantity="other">वाय-फाय नेटवर्क उपलब्ध</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">खुले वाय-फाय नेटवर्क उपलब्ध</item>
+ <item quantity="other">खुले वाय-फाय नेटवर्क उपलब्ध</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"वाय-फाय नेटवर्कवर साइन इन करा"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"नेटवर्क वर साइन इन करा"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ठीक"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"मीडिया हिव्हाइस म्हणून कनेक्ट केले"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"कॅमेरा म्हणून कनेक्ट केले"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"एक MIDI डिव्हाइस म्हणून कनेक्ट केले आहे"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"स्थापनकर्ता म्हणून कनेक्ट केले"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB उपसाधनावर कनेक्ट केले"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"अन्य USB पर्यायांसाठी स्पर्श करा."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 जुळणी"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"पूर्ण केले"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB संचयन अनमाउंट करत आहे…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD कार्ड अनमाउंट करत आहे…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"प्रतिबंध सुधारित करण्यासाठी पिन तयार करा"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"पिन जुळत नाहीत. पुन्हा प्रयत्न करा."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"पिन खूप लहान आहे. किमान 4 अंकांचा असणे आवश्यक आहे."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 सेकंदात पुन्हा प्रयत्न करा"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> सेकंदात पुन्हा प्रयत्न करा</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"नंतर पुन्हा प्रयत्न करा"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"पूर्ण स्क्रीनमधून निर्गमन करण्यासाठी शीर्षावरून खाली स्वाइप करा."</string>
<string name="done_label" msgid="2093726099505892398">"पूर्ण झाले"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"बॅटरीचे आयुष्य सुधारित करण्यात मदत करण्यासाठी, बॅटरी बचतकर्ता आपल्या डिव्हाइसचे कार्यप्रदर्शन कमी करतो आणि कंपन, स्थान सेवा आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. संकालनावर अवलंबून असणारे ईमेल, संदेशन आणि इतर अॅप्स आपण उघडल्याशिवाय अद्यतनित होऊ शकत नाहीत.\n\nआपले डिव्हाइस चार्ज होत असते तेव्हा बॅटरी बचतकर्ता स्वयंचलितपणे बंद होतो."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"आपला कार्य न करण्याचा कालावधी <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> वाजता समाप्त होईपर्यंत"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"आपला कार्य न करण्याचा कालावधी समाप्त होईपर्यंत"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"एका मिनिटासाठी (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> पर्यंत)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d मिनिटांसाठी (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> पर्यंत)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"एका तासासाठी (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> पर्यंत)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d तासांसाठी (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> पर्यंत)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"एक मिनिटासाठी"</item>
- <item quantity="other" msgid="6924190729213550991">"%d मिनिटांसाठी"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"एका तासासाठी"</item>
- <item quantity="other" msgid="5408537517529822157">"%d तासांसाठी"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d मिनिटासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="other">%1$d मिनिटांसाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d तासासाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ <item quantity="other">%1$d तासांसाठी (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> पर्यंत)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d मिनिटासाठी</item>
+ <item quantity="other">%d मिनिटांसाठी</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d तासासाठी</item>
+ <item quantity="other">%d तासांसाठी</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चितपणे"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"संक्षिप्त करा"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 21be5b19..31f5fab 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Kad SIM anda dikunci PUK. Taipkan kod PUK untuk membuka kuncinya."</string>
<string name="needPuk2" msgid="4526033371987193070">"Taipkan PUK2 untuk menyahsekat kad SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Tidak berjaya, dayakan Kunci SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi sebelum SIM dikunci."</item>
- <item quantity="other" msgid="7530597808358774740">"Anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi sebelum SIM dikunci."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Anda ada <xliff:g id="NUMBER_1">%d</xliff:g> cubaan lagi sebelum SIM dikunci.</item>
+ <item quantity="one">Anda ada <xliff:g id="NUMBER_0">%d</xliff:g> cubaan lagi sebelum SIM dikunci.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID Pemanggil Masuk"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ingin mendayakan Jelajah melalui Sentuhan. Apabila Jelajah melalui Sentuhan didayakan, anda boleh mendengar atau melihat penerangan tentang apa di bawah jari anda atau melakukan gerak isyarat untuk berinteraksi dengan telefon."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 bulan yang lalu"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Sebelum 1 bulan yang lalu"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 saat yang lalu"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> saat yang lalu"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minit yang lalu"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minit yang lalu"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 jam yang lalu"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> hari terakhir</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> hari terakhir</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Bulan lepas"</string>
<string name="older" msgid="5211975022815554840">"Lebih lama"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"semalam"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> hari yang lalu"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"dalam 1 saat"</item>
- <item quantity="other" msgid="1241926116443974687">"dalam <xliff:g id="COUNT">%d</xliff:g> saat"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"dalam 1 minit"</item>
- <item quantity="other" msgid="3330713936399448749">"dalam <xliff:g id="COUNT">%d</xliff:g> minit"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"dalam 1 jam"</item>
- <item quantity="other" msgid="547290677353727389">"dalam <xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"esok"</item>
- <item quantity="other" msgid="5109449375100953247">"dalam <xliff:g id="COUNT">%d</xliff:g> hari"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 saat yang lalu"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> saat yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 minit yang lalu"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> minit yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 jam yang lalu"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"semalam"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> hari yang lalu"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"dalam 1 saat"</item>
- <item quantity="other" msgid="5495880108825805108">"dalam <xliff:g id="COUNT">%d</xliff:g> saat"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"dalam 1 minit"</item>
- <item quantity="other" msgid="4216113292706568726">"dalam <xliff:g id="COUNT">%d</xliff:g> minit"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"dalam 1 jam"</item>
- <item quantity="other" msgid="3705373766798013406">"dalam <xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"esok"</item>
- <item quantity="other" msgid="2973062968038355991">"dalam <xliff:g id="COUNT">%d</xliff:g> hari"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"pada <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"pada <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"dalam <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"minggu"</string>
<string name="year" msgid="4001118221013892076">"tahun"</string>
<string name="years" msgid="6881577717993213522">"tahun"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 saat"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minit"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minit"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 jam"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> jam"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> saat</item>
+ <item quantity="one">1 saat</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minit</item>
+ <item quantity="one">1 minit</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> jam</item>
+ <item quantity="one">1 jam</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Masalah video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Maaf, video ini tidak sah untuk penstriman ke peranti ini."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tidak dapat mainkan video ini."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Tiada"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak diketahui"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Rangkaian Wi-Fi tersedia"</item>
- <item quantity="other" msgid="4192424489168397386">"Rangkaian Wi-Fi tersedia"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Rangkaian Wi-Fi terbuka tersedia"</item>
- <item quantity="other" msgid="7915895323644292768">"Rangkaian Wi-Fi terbuka tersedia"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Rangkaian Wi-Fi tersedia</item>
+ <item quantity="one">Rangkaian Wi-Fi tersedia</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Rangkaian Wi-Fi terbuka tersedia</item>
+ <item quantity="one">Rangkaian Wi-Fi terbuka tersedia</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Log masuk ke rangkaian Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Log masuk ke rangkaian"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Disambungkan sebagai peranti media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Disambungkan sebagai kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Disambungkan sebagai peranti MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Disambungkan sebagai pemasang"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Disambungkan kepada aksesori USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Sentuh untuk mendapatkan pilihan USB yang lain."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Langkau"</string>
<string name="no_matches" msgid="8129421908915840737">"Tiada padanan"</string>
<string name="find_on_page" msgid="1946799233822820384">"Cari di halaman"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 padanan"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> daripada <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> daripada <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 padanan</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Selesai"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Menyahlekap storan USB…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Menyahlekap kad SD…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Buat PIN untuk mengubah suai sekatan"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN tidak sepadan. Cuba lagi."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN terlalu pendek. Mesti sekurang-kurangnya 4 angka."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Cuba 1 saat lagi"</item>
- <item quantity="other" msgid="4730868920742952817">"Cuba <xliff:g id="COUNT">%d</xliff:g> saat lagi"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Cuba lagi dalam masa <xliff:g id="COUNT">%d</xliff:g> saat</item>
+ <item quantity="one">Cuba lagi dalam masa 1 saat</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Cuba sebentar lagi"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Leret ke bawah dari atas untuk keluar dari skrin penuh."</string>
<string name="done_label" msgid="2093726099505892398">"Selesai"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Untuk membantu memperbaik hayat bateri, penjimat bateri mengurangkan prestasi peranti anda dan menghadkan getaran, perkhidmatan lokasi dan kebanyakan data latar belakang. E-mel, pemesejan dan apl lain yang bergantung kepada penyegerakan mungkin tidak mengemas kini, melainkan anda membuka apl itu.\n\nPenjimat bateri dimatikan secara automatik semasa peranti anda sedang dicas."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Sehingga waktu gendala anda berakhir pada <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Sehingga waktu gendala anda berakhir"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Selama satu minit (sehingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Selama %1$d minit (sehingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Selama satu jam (sehingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Selama %1$d jam (sehingga <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item>
- <item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
- <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Selama %1$d minit (sehingga <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Selama satu minit (sehingga <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Selama %1$d jam (sehingga <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Selama satu jam (sehingga <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Selama %d minit</item>
+ <item quantity="one">Selama satu minit</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Selama %d jam</item>
+ <item quantity="one">Selama satu jam</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Selama-lamanya"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Runtuhkan"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index a8e95b5..ef52827 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ဆင်းမ်ကဒ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်။ ဖွင့်ရန် ကုဒ်အားထည့်သွင်းပါ။"</string>
<string name="needPuk2" msgid="4526033371987193070">"ဆင်းမ်ကဒ်အားမပိတ်ရန် PUK2အားထည့်သွင်းပါ"</string>
<string name="enablePin" msgid="209412020907207950">"မအောင်မြင်ပါ, SIM/RUIM သော့ကို အရင် သုံးခွင့်ပြုရန်"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"ဆင်းမ်ကဒ် သော့မကျခင် သင့်တွင် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။"</item>
- <item quantity="other" msgid="7530597808358774740">"နောက်ထပ် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစား၍ မအောင်မြင်ံပါက ဆင်းမ်ကဒ် သော့ကျသွားပါမည်။"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">ဆင်းမ်ကဒ် သော့မချခင် သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့်များကျန်ပါသေးသည်။</item>
+ <item quantity="one">ဆင်းမ်ကဒ် သော့မချခင် သင့်တွင် <xliff:g id="NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEIDနံပါတ်"</string>
<string name="ClipMmi" msgid="6952821216480289285">"အဝင်ခေါ်ဆိုမှုID"</string>
@@ -1131,73 +1131,12 @@
<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">"လွန်ခဲ့သော၁လက"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"လွန်ခဲ့သော၁လမတိုင်မီက"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"လွန်ခဲ့သော ၁စက္ကန့်က"</item>
- <item quantity="other" msgid="3903706804349556379">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> စက္ကန့်က"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"လွန်ခဲ့သော ၁မိနစ်က"</item>
- <item quantity="other" msgid="2176942008915455116">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> မိနစ်က"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"လွနခဲ့သော ၁နာရီက"</item>
- <item quantity="other" msgid="2467273239587587569">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> နာရီက"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> နောက်ဆုံး <xliff:g id="COUNT_1">%d</xliff:g> နေ့</item>
+ <item quantity="one"> နောက်ဆုံး <xliff:g id="COUNT_0">%d</xliff:g> နေ့ </item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"ပြီးခဲ့သောလ"</string>
<string name="older" msgid="5211975022815554840">"ယခင်က"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"မနေ့က"</item>
- <item quantity="other" msgid="2479586466153314633">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> ရက်တွင်"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"နောက် ၁စက္ကန့်တွင်"</item>
- <item quantity="other" msgid="1241926116443974687">"နောက် <xliff:g id="COUNT">%d</xliff:g> စက္ကန့်တွင်"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"နောက်၁မီနစ်တွင်"</item>
- <item quantity="other" msgid="3330713936399448749">"နောက် <xliff:g id="COUNT">%d</xliff:g> မိနစ်တွင်"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"နောက်၁နာရီတွင်"</item>
- <item quantity="other" msgid="547290677353727389">"နောက် <xliff:g id="COUNT">%d</xliff:g> နာရီတွင်"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"မနက်ဖြန်"</item>
- <item quantity="other" msgid="5109449375100953247">"နောက် <xliff:g id="COUNT">%d</xliff:g> ရက်တွင်"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"လွန်ခဲ့သော ၁စက္ကန့်က"</item>
- <item quantity="other" msgid="3699169366650930415">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> စက္ကန့်က"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"လွန်ခဲ့သော ၁မိနစ်က"</item>
- <item quantity="other" msgid="851164968597150710">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> မိနစ်က"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"လွန်ခဲ့သော ၁နာရီက"</item>
- <item quantity="other" msgid="6889970745748538901">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> နာရီက"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"မနေ့က"</item>
- <item quantity="other" msgid="3453342639616481191">"လွန်ခဲ့သော <xliff:g id="COUNT">%d</xliff:g> ရက်တွင်"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"နောက် ၁စက္ကန့်တွင်"</item>
- <item quantity="other" msgid="5495880108825805108">"နောက် <xliff:g id="COUNT">%d</xliff:g> စက္ကန့်တွင်"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"နောက်၁မိနစ်တွင်"</item>
- <item quantity="other" msgid="4216113292706568726">"နောက် <xliff:g id="COUNT">%d</xliff:g> မိနစ်တွင်"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"နောက်၁နာရီတွင်"</item>
- <item quantity="other" msgid="3705373766798013406">"နောက် <xliff:g id="COUNT">%d</xliff:g> နာရီတွင်"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"မနက်ဖြန်"</item>
- <item quantity="other" msgid="2973062968038355991">"နောက် <xliff:g id="COUNT">%d</xliff:g> ရက်တွင်"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> တွင်"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>မှာ"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>တွင်"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"အပတ်"</string>
<string name="year" msgid="4001118221013892076">"နှစ်"</string>
<string name="years" msgid="6881577717993213522">"နှစ်ပေါင်း"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"၁ စက္ကန့်"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> စက္ကန့်"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"၁ မိနစ်"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> မိနစ်"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"၁ နာရီ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> နာရီ"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> စက္ကန့်</item>
+ <item quantity="one">1 စက္ကန့်</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> မိနစ်</item>
+ <item quantity="one">1 မိနစ်</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> နာရီ</item>
+ <item quantity="one"> 1 နာရီ</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"တစ်ခုမှမဟုတ်"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"မြည်သံများ"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"မသိသောမြည်သံ"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"ဝိုင်ဖိုင်ကွန်ယက်ရှိသည်"</item>
- <item quantity="other" msgid="4192424489168397386">"ဝိုင်ဖိုင်ကွန်ယက်များရှိသည်"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"ဖွင့်ထားသောဝိုင်ဖိုင်ကွန်ယက်ရှိသည်"</item>
- <item quantity="other" msgid="7915895323644292768">"ဖွင့်ထားသောဝိုင်ဖိုင်ကွန်ယက်များရှိသည်"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi ကွန်ယက်များရရှိနိုင်သည်</item>
+ <item quantity="one">Wi-Fi ကွန်ယက်ရရှိနိုင်သည်</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Wi-Fi ကွန်ယက်များရရှိနိုင်သည်အား ဖွင့်ပါ</item>
+ <item quantity="one">Wi-Fi ကွန်ယက်ရရှိနိုင်သည်အား ဖွင့်ပါ</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ဝိုင်ဖိုင်ကွန်ရက်သို့ ဝင်ပါ"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ကွန်ရက်သို့ ဝင်ပါ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ကောင်းပြီ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"မီဒီယာစက်အနေဖြင့် ချိတ်ဆက်သည်"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"ကင်မရာအနေဖြင့်ဆက်သွယ်ခြင်း"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI စက်ပစ္စည်းအဖြစ် ချိတ်ဆက်ထားသည်"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"installerအနေဖြင့် ချိတ်ဆက်သည်"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USBတွဲဖက်ပစ္စည်းအား ချိတ်ဆက်ထားသည်"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"အခြား USB စိတ်ကြိုက်ရွေးချယ်ခွင့်များ အတွက် တို့ထိပါ။"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"တူညီချက်တစ်ခု"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ၏ <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>ထဲမှ <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">ကိုက်ညီမှု 1 ခု</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"ပြီးပါပြီ"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB သိုလှောင်မှု ကိရိယာအား ဆက်သွယ်မှု ရပ်ရန် ပြုလုပ်နေစဉ်…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD ကဒ်အား ဆက်သွယ်မှု ရပ်ရန် ပြုလုပ်နေစဉ်…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"ကန့်သတ်ချက်များ ပြင်ဆင်ခွင့်ပေးသော ပင်နံပါတ် သတ်မှတ်ပါ"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"ပင် နံပါတ် မတူပါ။ ထပ်ကြိုးစားပါ"</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"ပင် နံပါတ် တိုလွန်းသည်။. အနည်းဆုံး ဂဏန်း ၄ လုံး ဖြစ်ရမည်။"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"၁ စက္ကန့်အကြာတွင် ပြန်ကြိုးစားပါ"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> စက္ကန့်အကြာတွင် ပြန်ကြိုးစားပါ"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> စက္ကန့်အတွင်း ထပ်မံကြိုးစားပါ</item>
+ <item quantity="one">1 စက္ကန့်အတွင်း ထပ်မံကြိုးစားပါ</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"နောက်မှ ပြန်ကြိုးစားပါ"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"မျက်နှာပြင်အပြည့်ကနေ ပြန်ပြောင်းရန် အပေါ်အောက် ဆွဲချပါ"</string>
<string name="done_label" msgid="2093726099505892398">"ပြီးပါပြီ"</string>
@@ -1849,20 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ဘက်ထရီသက်တမ်း ကြာရှည်ခံရန်၊ ဘက်ထရီအားထိန်းသည် သင့်ကိရိယာ၏ ဆောင်ရွက်ချက်ကို လျှော့ပေးပြီး တုန်ခါမှု၊ တည်နေရာဝန်ဆောင်မှုများနှင့်၊ နောက်ခံဒေတာအများစုကို ကန့်သတ်ပေး၏။ စင့်လုပ်ပေးရလေ့ရှိသည့် အီးမေး၊ စာပို့ခြင်းနှင့်၊ အခြားအပလီကေးရှင်းများကို ၎င်းတို့အား သင် ဖွင့်မှသာ အဆင့်မြှင့်မွမ်းမံမည်ဖြစ်၏။ \n\n ကိရိယာအား အားသွင်းနေစဉ် ဘက်ထရီအားထိန်းအား အလိုအလျောက် ပိတ်ထားသည်။"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"သင်၏ စက်ရပ်ချိန် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> မှာ ပြီးဆုံးသည့် အထိ။"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"သင့်ကျချိန်အဆုံးအထိ"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"တစ်မိနစ်ကြာ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>အထိ)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d မိနစ်ကြာ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>အထိ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"တစ်နာရီကြာ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>အထိ)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d နာရီကြာ (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>အထိ)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"တစ်မိနစ် အတွင်း"</item>
- <item quantity="other" msgid="6924190729213550991">"%d မိနစ် အတွင်း"</item>
- </plurals>
- <!-- String.format failed for translation -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d မိနစ်တွင် (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>အထိ)</item>
+ <item quantity="one">တစ်မိနစ်တွင် (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> အထိ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d နာရီကြာ (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>အထိ)</item>
+ <item quantity="one">တစ်နာရီကြာ (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> အထိ)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d မိနစ်တွင်</item>
+ <item quantity="one">တစ်မိနစ်တွင်</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d နာရီကြာ</item>
+ <item quantity="one">တစ်နာရီကြာ</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>အထိ"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"အကန့်အသတ်မရှိစွာ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ခေါက်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 35147e4..16cd07a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM-kortet ditt er PUK-låst. Skriv inn PUK-koden for å låse det opp."</string>
<string name="needPuk2" msgid="4526033371987193070">"Skriv inn PUK2 for å låse opp SIM-kortet."</string>
<string name="enablePin" msgid="209412020907207950">"Mislyktes – aktiver lås for SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen før SIM-kortet låses."</item>
- <item quantity="other" msgid="7530597808358774740">"Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen før SIM-kortet låses."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøk igjen før SIM-kortet låses.</item>
+ <item quantity="one">Du har <xliff:g id="NUMBER_0">%d</xliff:g> forsøk igjen før SIM-kortet låses.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Inngående nummervisning"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ber om aktivering av Utforsk ved å trykke. Når Utforsk ved å trykke er slått på, kan du høre eller se beskrivelser av det som er under fingrene dine. Du kan også utføre handlinger på nettbrettet ved hjelp av bevegelser."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"For én måned siden"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"For over en måned siden"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"for et sekund siden"</item>
- <item quantity="other" msgid="3903706804349556379">"for <xliff:g id="COUNT">%d</xliff:g> sekunder siden"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"for et minutt siden"</item>
- <item quantity="other" msgid="2176942008915455116">"for <xliff:g id="COUNT">%d</xliff:g> minutter siden"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"for en time siden"</item>
- <item quantity="other" msgid="2467273239587587569">"for <xliff:g id="COUNT">%d</xliff:g> timer siden"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">De siste <xliff:g id="COUNT_1">%d</xliff:g> dagene</item>
+ <item quantity="one">Den siste <xliff:g id="COUNT_0">%d</xliff:g> dagen</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Forrige måned"</string>
<string name="older" msgid="5211975022815554840">"Eldre"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"i går"</item>
- <item quantity="other" msgid="2479586466153314633">"for <xliff:g id="COUNT">%d</xliff:g> dager siden"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"om et sekund"</item>
- <item quantity="other" msgid="1241926116443974687">"om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"om et minutt"</item>
- <item quantity="other" msgid="3330713936399448749">"om <xliff:g id="COUNT">%d</xliff:g> minutter"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"om et minutt"</item>
- <item quantity="other" msgid="547290677353727389">"om <xliff:g id="COUNT">%d</xliff:g> timer"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"i morgen"</item>
- <item quantity="other" msgid="5109449375100953247">"om <xliff:g id="COUNT">%d</xliff:g> dager"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 sek siden"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> sek siden"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 min siden"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> min siden"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 t siden"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> t siden"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"i går"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> d siden"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"om 1 sek"</item>
- <item quantity="other" msgid="5495880108825805108">"om <xliff:g id="COUNT">%d</xliff:g> sek"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"om 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"om <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"om 1 t"</item>
- <item quantity="other" msgid="3705373766798013406">"om <xliff:g id="COUNT">%d</xliff:g> t"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"i morgen"</item>
- <item quantity="other" msgid="2973062968038355991">"om <xliff:g id="COUNT">%d</xliff:g> d"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"i <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"uker"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"Ett sekund"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"Ett minutt"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutter"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"Én time"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timer"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="one">1 sekund</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutter</item>
+ <item quantity="one">1 minutt</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> timer</item>
+ <item quantity="one">1 time</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Denne videoen er ikke gyldig for direkteavspilling på enheten."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Kan ikke spille av denne videoen."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Ukjent ringetone"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Trådløsnett i nærheten"</item>
- <item quantity="other" msgid="4192424489168397386">"Trådløsnett i nærheten"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Åpent trådløsnett i nærheten"</item>
- <item quantity="other" msgid="7915895323644292768">"Åpne trådløsnett i nærheten"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi-nettverk er tilgjengelig</item>
+ <item quantity="one">Wi-Fi-nettverk er tilgjengelig</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Åpne Wi-Fi-nettverk er tilgjengelig</item>
+ <item quantity="one">Åpent Wi-Fi-nettverk er tilgjengelig</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Pålogging til Wi-Fi-nettverk"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Logg på nettverket"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilkoblet som medieenhet"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilkoblet som kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Koblet til som MIDI-enhet"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilkoblet som installasjonsprogram"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Koblet til et USB-tilbehør"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Trykk for få andre USB-alternativer."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Hopp over"</string>
<string name="no_matches" msgid="8129421908915840737">"Ingen treff"</string>
<string name="find_on_page" msgid="1946799233822820384">"Finn på side"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 treff"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 kamp</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Ferdig"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Kobler fra USB-lagringen …"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Kobler fra SD-kort …"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Angi en PIN-kode for endring av begrensninger"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-kodene stemmer ikke overens. Prøv på nytt."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN-koden er for kort. Den må bestå av minst fire sifre."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Prøv på nytt om 1 sekund"</item>
- <item quantity="other" msgid="4730868920742952817">"Prøv på nytt om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Prøv på nytt om <xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="one">Prøv på nytt om 1 sekund</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Prøv på nytt senere"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Sveip ned fra toppen av skjermen for å gå ut av fullskjermvisningen."</string>
<string name="done_label" msgid="2093726099505892398">"Ferdig"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"For å bidra til å forbedre batterilevetiden reduserer batterispareren ytelsen til enheten din og begrenser vibrering, posisjonstjenester og mesteparten av bakgrunnsdataene. E-post, sending av meldinger og andre apper som er avhengig av synkronisering oppdateres kanskje ikke med mindre du åpner dem.\n\nBatterisparing slås av automatisk når enheten lader."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Til hviletiden din ender kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Inntil nedetiden din er over"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"I ett minutt (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"I %1$d minutter (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"I én time (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"I %1$d timer (til <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"I ett minutt"</item>
- <item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"I én time"</item>
- <item quantity="other" msgid="5408537517529822157">"I %d timer"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">I %1$d minutter (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">I 1 minutt (til <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">For %1$d timer (til <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">I 1 time (til <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">I %d minutter</item>
+ <item quantity="one">I 1 minutt</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">I %d timer</item>
+ <item quantity="one">I 1 time</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"På ubestemt tid"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Skjul"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 093f3c9..b705d62 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"तपाईंको SIM कार्ड PUK-लक छ। यसलाई अनलक गर्न PUK कोड टाइप गर्नुहोस्।"</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM कार्ड अनलक गर्न PUK2 टाइप गर्नुहोस्।"</string>
<string name="enablePin" msgid="209412020907207950">"असफल, SIM/RUIM बन्द छ।"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"तपाईंसँग SIM बन्द हुनु अघि <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयास छ।"</item>
- <item quantity="other" msgid="7530597808358774740">"SIM बन्द हुनु अघि तपाईंसँग <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयासहरू छन्।"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">तपाईंसँग SIM बन्द हुनु अघि <xliff:g id="NUMBER_1">%d</xliff:g> बाँकी प्रयासहरू छन्।</item>
+ <item quantity="one">तपाईंसँग SIM बन्द हुनु अघि <xliff:g id="NUMBER_0">%d</xliff:g> प्रयास बाँकी छ।</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"आगमन कलर ID"</string>
@@ -1131,73 +1131,12 @@
<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">"१ महिना अघि"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"१ महिना अघि"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"१ सेकेन्ड अघि"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्ड अघि"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"१ मिनेट अघि"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> मिनेट अघि"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"१ घन्टा अघि"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> घन्टा अघि"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> अन्तिम <xliff:g id="COUNT_1">%d</xliff:g> दिन</item>
+ <item quantity="one"> अन्तिम <xliff:g id="COUNT_0">%d</xliff:g> दिन</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"अन्तिम महिना"</string>
<string name="older" msgid="5211975022815554840">"पुरानो"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"हिजो"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> दिन अघि"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"१ सेकेन्डमा"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"१ मिनेटमा"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g>मिनेटमा"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"१ घन्टामा"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> घन्टामा"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"भोलि"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> दिनमा"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"१ सेकेन्ड अघि"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्ड अगाडि"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"१ मिनेट अघि"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> मिनेट अघि"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"१ घन्टा अघि"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> घन्टा अघि"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"हिजो"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> दिन अघि"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"१ सेकन्ड"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"१ मिनेटमा"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> मिनेटमा"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"१ घन्टामा"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> घन्टामा"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"भोलि"</item>
- <item quantity="other" msgid="2973062968038355991">"दिन<xliff:g id="COUNT">%d</xliff:g> मा"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> मा"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> मा"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> मा"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"हप्ताहरू"</string>
<string name="year" msgid="4001118221013892076">"वर्ष"</string>
<string name="years" msgid="6881577717993213522">"वर्षहरू"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"१ सेकेन्ड"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्ड"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"१ मिनेट"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> मिनेट"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"१ घन्टा"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> घन्टा"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> सेकेन्ड</item>
+ <item quantity="one">1 सेकेन्ड</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> मिनेट</item>
+ <item quantity="one">1 मिनेट</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> घण्टा</item>
+ <item quantity="one">1 घण्टा</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>
@@ -1339,14 +1278,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"कुनै पनि होइन"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"घन्टीका स्वरहरू"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिङटोन"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"वाइफाइ नेटवर्क उपलब्ध छ"</item>
- <item quantity="other" msgid="4192424489168397386">"वाइफाइ नेटवर्कहरू उपलब्ध"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"खुल्ला वाइफाइ नेटवर्क उपलब्ध छ"</item>
- <item quantity="other" msgid="7915895323644292768">"खुल्ला वाइफाइ नेटवर्क उपलब्ध छ"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi सञ्जालहरू उपलब्ध छन्</item>
+ <item quantity="one">Wi-Fi सञ्जाल उपलब्ध छ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other"> खुल्ला Wi-Fi सञ्जालहरू उपलब्ध छन्</item>
+ <item quantity="one">खुल्ला Wi-Fi सञ्जाल उपलब्ध छ</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"वाइफाइ नेटवर्कमा साइन गर्नुहोस्"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"नेटवर्कमा साइन गर्नुहोस्।"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1422,6 +1361,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ठिक छ"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"मिडिया उपकरणको रूपमा जडित"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"क्यामेराको रूपमा जडान भएको"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI उपकरणको रूपमा जडान गरियो"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"एउटा स्थापनकर्ताको रूपमा जोडिएको छ"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB सहायकमा जोडिएको छ"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"अन्य USB विकल्पहरूको लागि टच गर्नुहोस्।"</string>
@@ -1537,10 +1477,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"१ मेल"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> को <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> को<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 मेल</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"भयो"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB भण्डारण अनमाउन्ट गर्दै..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD कार्ड अनमाउन्ट गर्दै…"</string>
@@ -1826,10 +1766,10 @@
<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_too_short" msgid="8173982756265777792">"PIN अति छोटो भयो। कम्तीमा ४ अङ्क हुन आवश्यक छ।"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"१ सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा पुनः प्रयास गर्नुहोस्"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"> फेरि <xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्</item>
+ <item quantity="one">1 सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"पछि पुनः प्रयास गर्नुहोस्"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"पूर्णस्क्रिनबाट बाहिर निस्कन माथिबाट तलतिर स्वाइप गर्नुहोस्।"</string>
<string name="done_label" msgid="2093726099505892398">"भयो"</string>
@@ -1855,22 +1795,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"ब्याट्रीको आयु सुधार्न, ब्याट्री रक्षकले तपाईँको यन्त्रको कार्यसम्पादन घटाउँछ र भाइब्रेसन, स्थान सेवा र बहुसंख्यक पृष्ठभूमि डेटा सीमित गर्दछ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जुन सिङ्कमा भर पर्छन् अद्यावधिक नहुन सक्छन् जबसम्म तपाईँ तिनीहरूलाई खोल्नुहुन्न\n\n ब्याट्री रक्षक स्वत: निस्कृय हुन्छ जब तपाईँको यन्त्र चार्ज हुँदै हुन्छ।"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"तपाईँको <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> डाउनटाइम समाप्त हुँदा सम्म"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"तपाईँको डाउनटाइम समाप्त नभए सम्म"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"एक मिनेटको लागि (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> सम्म)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d मिनेटको लागि (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> सम्म)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"एक घण्टाको लागि (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> सम्म)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d घण्टाको लागि (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> सम्म)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"एक मिनेटको लागि"</item>
- <item quantity="other" msgid="6924190729213550991">"%d मिनेटको लागि"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"एक घण्टाको लागि"</item>
- <item quantity="other" msgid="5408537517529822157">"%d घण्टाको लागि"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other"> %1$d मिनेटको लागि (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> सम्म)</item>
+ <item quantity="one">एक मिनेटको लागि (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> सम्म)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other"> %1$d घण्टाको लागि (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> सम्म)</item>
+ <item quantity="one">एक घण्टाको लागि (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> सम्म)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d मिनेटको लागि</item>
+ <item quantity="one">एक मिनेटको लागि</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d घण्टाको लागि</item>
+ <item quantity="one">एक घण्टाको लागि</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> सम्म"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"संक्षिप्त पार्नुहोस्"</string>
diff --git a/core/res/res/values-night/themes_material_daynight.xml b/core/res/res/values-night/themes_material_daynight.xml
new file mode 100644
index 0000000..da870b7
--- /dev/null
+++ b/core/res/res/values-night/themes_material_daynight.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see themes_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+<resources>
+
+ <!-- Material theme (day/night version) for activities. -->
+ <style name="Theme.Material.DayNight" parent="Theme.Material" />
+
+ <!-- Variant of Material.DayNight that has a solid (opaque) action bar
+ with an inverse color profile. The dark action bar sharply stands out against
+ the light content (when applicable). -->
+ <style name="Theme.Material.DayNight.DarkActionBar" parent="Theme.Material" />
+
+ <!-- Variant of Material.DayNight with no action bar. -->
+ <style name="Theme.Material.DayNight.NoActionBar" parent="Theme.Material.NoActionBar" />
+
+ <!-- Variant of Material.DayNight that has no title bar and fills
+ the entire screen. This theme
+ sets {@link android.R.attr#windowFullscreen} to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen" />
+
+ <!-- Variant of Material.DayNight that has no title bar and fills
+ the entire screen and extends into the display overscan region. This theme
+ sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
+ to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan" />
+
+ <!-- Variant of Material.DayNight that has no title bar and translucent
+ system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
+ {@link android.R.attr#windowTranslucentNavigation} to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor" />
+
+ <!-- Default Material.DayNight theme for panel windows. This removes all extraneous
+ window decorations, so you basically have an empty rectangle in which
+ to place your content. It makes the window floating, with a transparent
+ background, and turns off dimming behind the window. -->
+ <style name="Theme.Material.DayNight.Panel" parent="Theme.Material.Panel" />
+
+ <!-- Material theme (day/night version) for dialog windows and activities,
+ which is used by the {@link android.app.Dialog} class. This changes
+ the window to be floating (not fill the entire screen), and puts a
+ frame around its contents. You can set this theme on an activity if
+ you would like to make an activity that looks like a Dialog. -->
+ <style name="Theme.Material.DayNight.Dialog" parent="Theme.Material.DayNight.BaseDialog" />
+ <style name="Theme.Material.DayNight.BaseDialog" parent="Theme.Material.BaseDialog" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that has a nice minimum width for
+ a regular dialog. -->
+ <style name="Theme.Material.DayNight.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that does not include a title bar. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a nice minimum width for
+ a regular dialog. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that has a fixed size. -->
+ <style name="Theme.Material.DayNight.Dialog.FixedSize" parent="Theme.Material.Dialog.FixedSize" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a fixed size. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar.FixedSize" parent="Theme.Material.Dialog.NoActionBar.FixedSize" />
+
+ <!-- Theme for a window that will be displayed either full-screen on
+ smaller screens (small, normal) or as a dialog on larger screens
+ (large, xlarge). -->
+ <style name="Theme.Material.DayNight.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge" />
+
+ <!-- Theme for a window without an action bar that will be displayed either full-screen
+ on smaller screens (small, normal) or as a dialog on larger screens
+ (large, xlarge). -->
+ <style name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar" />
+
+ <!-- Theme for a presentation window on a secondary display. -->
+ <style name="Theme.Material.DayNight.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation" />
+
+ <!-- Material user theme for alert dialog windows, which is used by the
+ {@link android.app.AlertDialog} class. -->
+ <style name="Theme.Material.DayNight.Dialog.Alert" parent="Theme.Material.DayNight.Dialog.BaseAlert" />
+ <style name="Theme.Material.DayNight.Dialog.BaseAlert" parent="Theme.Material.Dialog.BaseAlert" />
+
+ <style name="Theme.Material.DayNight.SearchBar" parent="Theme.Material.SearchBar" />
+ <style name="Theme.Material.DayNight.CompactMenu" parent="Theme.Material.CompactMenu" />
+
+</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0aff860..6be8c88 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Uw SIM-kaart is vergrendeld met de PUK-code. Typ de PUK-code om te ontgrendelen."</string>
<string name="needPuk2" msgid="4526033371987193070">"Voer de PUK2-code in om de SIM-kaart te ontgrendelen."</string>
<string name="enablePin" msgid="209412020907207950">"Mislukt. Schakel SIM/RUIM-vergrendeling in."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"U heeft nog <xliff:g id="NUMBER">%d</xliff:g> poging over voordat de simkaart wordt vergrendeld."</item>
- <item quantity="other" msgid="7530597808358774740">"U heeft nog <xliff:g id="NUMBER">%d</xliff:g> pogingen over voordat de simkaart wordt vergrendeld."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">U heeft nog <xliff:g id="NUMBER_1">%d</xliff:g> pogingen over voordat de simkaart wordt vergrendeld.</item>
+ <item quantity="one">U heeft nog <xliff:g id="NUMBER_0">%d</xliff:g> poging over voordat de simkaart wordt vergrendeld.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Inkomende beller-id"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder uw vinger staat of aanraakbewerkingen uitvoeren op de telefoon."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 maand geleden"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Meer dan 1 maand geleden"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 seconde geleden"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> seconden geleden"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuut geleden"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minuten geleden"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 uur geleden"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> uur geleden"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Afgelopen <xliff:g id="COUNT_1">%d</xliff:g> dagen</item>
+ <item quantity="one">Afgelopen <xliff:g id="COUNT_0">%d</xliff:g> dag</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Afgelopen maand"</string>
<string name="older" msgid="5211975022815554840">"Ouder"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"gisteren"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> dagen geleden"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"over 1 seconde"</item>
- <item quantity="other" msgid="1241926116443974687">"over <xliff:g id="COUNT">%d</xliff:g> seconden"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"over 1 minuut"</item>
- <item quantity="other" msgid="3330713936399448749">"over <xliff:g id="COUNT">%d</xliff:g> minuten"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"over 1 uur"</item>
- <item quantity="other" msgid="547290677353727389">"over <xliff:g id="COUNT">%d</xliff:g> uur"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"morgen"</item>
- <item quantity="other" msgid="5109449375100953247">"over <xliff:g id="COUNT">%d</xliff:g> dagen"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 seconde geleden"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> seconden geleden"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 minuut geleden"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> minuten geleden"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 uur geleden"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> uur geleden"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"gisteren"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> dagen geleden"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"over 1 seconde"</item>
- <item quantity="other" msgid="5495880108825805108">"over <xliff:g id="COUNT">%d</xliff:g> seconden"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"over 1 minuut"</item>
- <item quantity="other" msgid="4216113292706568726">"over <xliff:g id="COUNT">%d</xliff:g> minuten"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"over 1 uur"</item>
- <item quantity="other" msgid="3705373766798013406">"over <xliff:g id="COUNT">%d</xliff:g> uur"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"morgen"</item>
- <item quantity="other" msgid="2973062968038355991">"over <xliff:g id="COUNT">%d</xliff:g> dagen"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"op <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"om <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"in <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"weken"</string>
<string name="year" msgid="4001118221013892076">"jaar"</string>
<string name="years" msgid="6881577717993213522">"jaren"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 seconde"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> seconden"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuten"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 uur"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> uur"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> seconden</item>
+ <item quantity="one">1 seconde</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuten</item>
+ <item quantity="one">1 minuut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> uur</item>
+ <item quantity="one">1 uur</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Probleem met video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Deze video kan niet worden gestreamd naar dit apparaat."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Deze video kan niet worden afgespeeld."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Beltonen"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende beltoon"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wifi-netwerk beschikbaar"</item>
- <item quantity="other" msgid="4192424489168397386">"Wifi-netwerken beschikbaar"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Open wifi-netwerk beschikbaar"</item>
- <item quantity="other" msgid="7915895323644292768">"Open wifi-netwerken beschikbaar"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wifi-netwerken beschikbaar</item>
+ <item quantity="one">Wifi-netwerk beschikbaar</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Open wifi-netwerken beschikbaar</item>
+ <item quantity="one">Open wifi-netwerk beschikbaar</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Inloggen op wifi-netwerk"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Inloggen bij netwerk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Gekoppeld als media-apparaat"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Gekoppeld als camera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Verbonden als MIDI-apparaat"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Gekoppeld als installatieprogramma"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Aangesloten op een USB-accessoire"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Raak aan voor andere USB-opties."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Overslaan"</string>
<string name="no_matches" msgid="8129421908915840737">"Geen overeenkomsten"</string>
<string name="find_on_page" msgid="1946799233822820384">"Zoeken op pagina"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 overeenkomst"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 overeenkomst</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Gereed"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB-opslag ontkoppelen..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD-kaart ontkoppelen..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Maak een pincode voor het aanpassen van beperkingen"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"De pincodes komen niet overeen. Probeer het opnieuw."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Pincode is te kort. Moet ten minste vier cijfers lang zijn."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Probeer het over één seconde opnieuw"</item>
- <item quantity="other" msgid="4730868920742952817">"Probeer het over <xliff:g id="COUNT">%d</xliff:g> seconden opnieuw"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Probeer het over <xliff:g id="COUNT">%d</xliff:g> seconden opnieuw</item>
+ <item quantity="one">Probeer het over 1 seconde opnieuw</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Probeer het later opnieuw"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Veeg omlaag vanaf de bovenkant om het volledige scherm te sluiten."</string>
<string name="done_label" msgid="2093726099505892398">"Gereed"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Accubesparing beperkt de prestaties van uw apparaat, de trilstand, locatieservices en de meeste achtergrondgegevens om de gebruiksduur van de accu te verlengen.\n\nAccubesparing wordt automatisch uitgeschakeld terwijl uw apparaat wordt opgeladen."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat uw downtime eindigt om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Tot uw downtime afloopt"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Eén minuut (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d minuten (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Eén uur (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d uur (tot <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Eén minuut"</item>
- <item quantity="other" msgid="6924190729213550991">"%d minuten"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Eén uur"</item>
- <item quantity="other" msgid="5408537517529822157">"%d uur"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d minuten (tot <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Eén minuut (tot <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d uur (tot <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Eén uur (tot <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d minuten</item>
+ <item quantity="one">Eén minuut</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d uur</item>
+ <item quantity="one">Eén uur</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Voor onbepaalde tijd"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Samenvouwen"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 2b25918..04d4d09 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"Karta SIM jest zablokowana kodem PUK. Wprowadź kod PUK, aby odblokować kartę."</string>
<string name="needPuk2" msgid="4526033371987193070">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Nie udało się. Włącz blokadę karty SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> próbę, zanim karta SIM zostanie zablokowana."</item>
- <item quantity="other" msgid="7530597808358774740">"Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> prób(y), zanim karta SIM zostanie zablokowana."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="few">Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie zablokowana.</item>
+ <item quantity="many">Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> prób, zanim karta SIM zostanie zablokowana.</item>
+ <item quantity="other">Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie zablokowana.</item>
+ <item quantity="one">Masz jeszcze <xliff:g id="NUMBER_0">%d</xliff:g> próbę, zanim karta SIM zostanie zablokowana.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Nazwa rozmówcy przy połączeniach przychodzących"</string>
@@ -1131,73 +1133,14 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> chce włączyć Czytanie dotykiem. Gdy ta funkcja jest włączona, słyszysz i widzisz opisy elementów, które są pod Twoim palcem, oraz możesz obsługiwać telefon gestami."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 miesiąc temu"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Ponad 1 miesiąc temu"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"sekundę temu"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sek. temu"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minutę temu"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> min temu"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"godzinę temu"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> godz. temu"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="few">Ostatnie <xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+ <item quantity="many">Ostatnich <xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+ <item quantity="other">Ostatnie <xliff:g id="COUNT_1">%d</xliff:g> dnia</item>
+ <item quantity="one">Ostatni <xliff:g id="COUNT_0">%d</xliff:g> dzień</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Ostatni miesiąc"</string>
<string name="older" msgid="5211975022815554840">"Starsze"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"wczoraj"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> dni temu"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"za sekundę"</item>
- <item quantity="other" msgid="1241926116443974687">"za <xliff:g id="COUNT">%d</xliff:g> sek."</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"za minutę"</item>
- <item quantity="other" msgid="3330713936399448749">"za <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"za godzinę"</item>
- <item quantity="other" msgid="547290677353727389">"za <xliff:g id="COUNT">%d</xliff:g> godzin"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"jutro"</item>
- <item quantity="other" msgid="5109449375100953247">"za <xliff:g id="COUNT">%d</xliff:g> dni"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"sekundę temu"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> s temu"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"minutę temu"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> min temu"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"godzinę temu"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> godz. temu"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"wczoraj"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> dni temu"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"za sekundę"</item>
- <item quantity="other" msgid="5495880108825805108">"za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"za minutę"</item>
- <item quantity="other" msgid="4216113292706568726">"za <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"za godzinę"</item>
- <item quantity="other" msgid="3705373766798013406">"za <xliff:g id="COUNT">%d</xliff:g> godz."</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"jutro"</item>
- <item quantity="other" msgid="2973062968038355991">"za <xliff:g id="COUNT">%d</xliff:g> dni"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"w dniu <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"o godzinie <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"w <xliff:g id="YEAR">%s</xliff:g> r."</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"tygodni"</string>
<string name="year" msgid="4001118221013892076">"rok"</string>
<string name="years" msgid="6881577717993213522">"lat"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 godzina"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> godz."</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="one">1 sekunda</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minuty</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> minut</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuty</item>
+ <item quantity="one">1 minuta</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> godziny</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> godzin</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> godziny</item>
+ <item quantity="one">1 godzina</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problem z filmem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ten film nie nadaje się do strumieniowego przesyłania do tego urządzenia."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nie można odtworzyć tego filmu."</string>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Brak"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Dzwonki"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nieznany dzwonek"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Sieć Wi-Fi jest dostępna"</item>
- <item quantity="other" msgid="4192424489168397386">"Dostępne sieci Wi-Fi"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Otwórz dostępne sieci Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"Otwórz dostępne sieci Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="few">Dostępne są sieci Wi-Fi</item>
+ <item quantity="many">Dostępne są sieci Wi-Fi</item>
+ <item quantity="other">Dostępne są sieci Wi-Fi</item>
+ <item quantity="one">Dostępna jest sieć Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="few">Dostępne są otwarte sieci Wi-Fi</item>
+ <item quantity="many">Dostępne są otwarte sieci Wi-Fi</item>
+ <item quantity="other">Dostępne są otwarte sieci Wi-Fi</item>
+ <item quantity="one">Dostępna jest otwarta sieć Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Zaloguj się do sieci Wi-Fi."</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Zaloguj się do sieci"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Podłączono urządzenie multimedialne"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Podłączono jako aparat."</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Podłączono jako urządzenie MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Podłączono jako nośnik instalacyjny."</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Podłączono akcesorium USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Dotknij, aby wyświetlić inne opcje USB."</string>
@@ -1531,10 +1485,12 @@
<string name="skip_button_label" msgid="1275362299471631819">"Pomiń"</string>
<string name="no_matches" msgid="8129421908915840737">"Brak wyników"</string>
<string name="find_on_page" msgid="1946799233822820384">"Znajdź na stronie"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 wynik"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 dopasowanie</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Gotowe"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Odłączanie nośnika USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Odłączanie karty SD..."</string>
@@ -1656,7 +1612,7 @@
<string name="wireless_display_route_description" msgid="9070346425023979651">"Wyświetlacz bezprzewodowy"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Przesyłaj"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Połącz z urządzeniem"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Prezentuj ekran na urządzeniu"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Prześlij ekran na urządzenie"</string>
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Szukam urządzeń…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Ustawienia"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Rozłącz"</string>
@@ -1820,10 +1776,12 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Utwórz PIN wymagany przy zmianie ograniczeń"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Kody PIN nie są identyczne. Spróbuj ponownie."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN jest za krótki. Musi mieć co najmniej 4 cyfry."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Spróbuj za sekundę"</item>
- <item quantity="other" msgid="4730868920742952817">"Spróbuj za <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="few">Spróbuj ponownie za <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many">Spróbuj ponownie za <xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ <item quantity="other">Spróbuj ponownie za <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <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_mode_confirmation" msgid="7227416894979047467">"Przesuń z góry w dół, by zamknąć pełny ekran."</string>
<string name="done_label" msgid="2093726099505892398">"Gotowe"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Aby wydłużyć czas pracy baterii, Oszczędzanie baterii ogranicza aktywność urządzenia, w tym wibracje, usługi lokalizacyjne i przetwarzanie większości danych w tle. Poczta, czat i inne synchronizowane aplikacje mogą nie aktualizować swojej zawartości, dopóki ich nie otworzysz.\n\nOszczędzanie baterii wyłącza się automatycznie podczas ładowania urządzenia."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Do zakończenia przestoju o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Do zakończenia wyłączenia"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Przez minutę (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Przez %1$d min (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Przez godzinę (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Przez %1$d godz. (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Przez minutę"</item>
- <item quantity="other" msgid="6924190729213550991">"Przez %d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Przez 1 godz."</item>
- <item quantity="other" msgid="5408537517529822157">"Przez %d godz."</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="few">Przez %1$d minuty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">Przez %1$d minut (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Przez %1$d minuty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Przez minutę (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="few">Przez %1$d godziny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">Przez %1$d godzin (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Przez %1$d godziny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Przez godzinę (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="few">Przez %d minuty</item>
+ <item quantity="many">Przez %d minut</item>
+ <item quantity="other">Przez %d minuty</item>
+ <item quantity="one">Przez minutę</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="few">Przez %d godziny</item>
+ <item quantity="many">Przez %d godzin</item>
+ <item quantity="other">Przez %d godziny</item>
+ <item quantity="one">Przez godzinę</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Na czas nieokreślony"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Zwiń"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 041847d..8b3511e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado."</item>
- <item quantity="other" msgid="7530597808358774740">"Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
+ <item quantity="one">Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID do Autor da Chamada"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> pretende ativar a funcionalidade Explorar Através do Toque. Quando a funcionalidade Explorar Através do Toque estiver ativada, pode ouvir ou visualizar descrições sobre o que está por baixo do seu dedo ou executar gestos para interagir com o telemóvel."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Há 1 mês"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Há mais de 1 mês"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Há 1 segundo"</item>
- <item quantity="other" msgid="3903706804349556379">"Há <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Há 1 minuto"</item>
- <item quantity="other" msgid="2176942008915455116">"Há <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Há 1 hora"</item>
- <item quantity="other" msgid="2467273239587587569">"Há <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+ <item quantity="one">Último <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Último mês"</string>
<string name="older" msgid="5211975022815554840">"Mais antiga"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ontem"</item>
- <item quantity="other" msgid="2479586466153314633">"Há <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"daqui a 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"daqui a <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"daqui a 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"daqui a <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"daqui a 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"daqui a <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"amanhã"</item>
- <item quantity="other" msgid="5109449375100953247">"daqui a <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Há 1 seg"</item>
- <item quantity="other" msgid="3699169366650930415">"Há <xliff:g id="COUNT">%d</xliff:g> seg"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"há 1 min"</item>
- <item quantity="other" msgid="851164968597150710">"Há <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Há 1 hora"</item>
- <item quantity="other" msgid="6889970745748538901">"Há <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ontem"</item>
- <item quantity="other" msgid="3453342639616481191">"Há <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"daqui a 1 seg"</item>
- <item quantity="other" msgid="5495880108825805108">"daqui a <xliff:g id="COUNT">%d</xliff:g> seg"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"daqui a 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"daqui a <xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"daqui a 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"em <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"amanhã"</item>
- <item quantity="other" msgid="2973062968038355991">"daqui a <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"a <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"em <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"ano"</string>
<string name="years" msgid="6881577717993213522">"anos"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">1 segundo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ <item quantity="one">1 minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ <item quantity="one">1 hora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão em fluxo contínuo neste aparelho."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nada"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Rede Wi-Fi disponível"</item>
- <item quantity="other" msgid="4192424489168397386">"Redes Wi-Fi disponíveis"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
- <item quantity="other" msgid="7915895323644292768">"Abrir redes Wi-Fi disponíveis"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Redes Wi-Fi disponíveis</item>
+ <item quantity="one">Rede Wi-Fi disponível</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Redes Wi-Fi abertas disponíveis</item>
+ <item quantity="one">Rede Wi-Fi aberta disponível</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Iniciar sessão na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Inicie sessão na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um dispositivo multimédia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ligado como uma câmara"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Ligado como um dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ligado como um instalador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ligado a um acessório USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toque para ver outras opções USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ignorar"</string>
<string name="no_matches" msgid="8129421908915840737">"Sem correspondências"</string>
<string name="find_on_page" msgid="1946799233822820384">"Localizar na página"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 correspondência"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 correspondência</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Concluído"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"A desmontar memória de armazenamento USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"A desmontar cartão SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crie um PIN para modificar as restrições"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PINs não correspondem. Tente novamente."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Tente em: 1 seg"</item>
- <item quantity="other" msgid="4730868920742952817">"Tente em: <xliff:g id="COUNT">%d</xliff:g> seg"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="one">Tente novamente dentro de 1 segundo</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Tente novamente mais tarde"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Deslize rapidamente para baixo para sair do ecrã inteiro."</string>
<string name="done_label" msgid="2093726099505892398">"Concluído"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Para ajudar a melhorar a autonomia da bateria, a poupança de bateria reduz o desempenho do seu dispositivo e limita a vibração, os serviços de localização e a maioria dos dados em segundo plano. O email, as mensagens e outras aplicações que dependem da sincronização não podem ser atualizados exceto se os abrir.\n\nA poupança de bateria desliga-se automaticamente quando o dispositivo está a carregar."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Até terminar o período de inatividade"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Durante um minuto (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Durante %1$d minutos (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Durante uma hora (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Durante %1$d horas (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Durante um minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Durante uma hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Durante %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante um minuto (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Durante %1$d horas (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Durante uma hora (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Durante %d minutos</item>
+ <item quantity="one">Durante um minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Durante %d horas</item>
+ <item quantity="one">Durante uma hora</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Reduzir"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4ea2f18..acc9d41 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
<string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o cartão SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Falha. Ative o bloqueio do SIM/R-UIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado."</item>
- <item quantity="other" msgid="7530597808358774740">"Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
+ <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM será bloqueado.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID do chamador de entrada"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quer ativar a exploração pelo toque. Com ela, você pode ouvir ou ver descrições do que está sob seu dedo e interagir com o telefone através de gestos."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 mês atrás"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Antes de 1 mês atrás"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 segundo atrás"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> segundos atrás"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuto atrás"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minutos atrás"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 hora atrás"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> horas atrás"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+ <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Mês passado"</string>
<string name="older" msgid="5211975022815554840">"Mais antigos"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ontem"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> dias atrás"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"em 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"em <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"em 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"em <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"em 1 hora"</item>
- <item quantity="other" msgid="547290677353727389">"Em <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"amanhã"</item>
- <item quantity="other" msgid="5109449375100953247">"em <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 seg. atrás"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> segundos atrás"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 minuto atrás"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> minutos atrás"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 hora atrás"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> horas atrás"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ontem"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> dias atrás"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"em 1 segundo"</item>
- <item quantity="other" msgid="5495880108825805108">"em <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"em 1 minuto"</item>
- <item quantity="other" msgid="4216113292706568726">"em <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"em 1 hora"</item>
- <item quantity="other" msgid="3705373766798013406">"em <xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"amanhã"</item>
- <item quantity="other" msgid="2973062968038355991">"em <xliff:g id="COUNT">%d</xliff:g> dias"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"em <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"às <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"em <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"semanas"</string>
<string name="year" msgid="4001118221013892076">"ano"</string>
<string name="years" msgid="6881577717993213522">"anos"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"Um segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"Um minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minutos"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"Uma hora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> horas"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minutos</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> horas</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão neste dispositivo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Não é possível reproduzir este vídeo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Nenhum"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Rede Wi-Fi disponível"</item>
- <item quantity="other" msgid="4192424489168397386">"Redes Wi-Fi disponíveis"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
- <item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abertas disponíveis"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Redes Wi-Fi disponíveis</item>
+ <item quantity="other">Redes Wi-Fi disponíveis</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Abrir redes Wi-Fi disponíveis</item>
+ <item quantity="other">Abrir redes Wi-Fi disponíveis</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Fazer login na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Acessar a rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como um dispositivo de mídia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como câmera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectado como dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectados como um instalador"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectado a um acessório USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Toque para obter outras opções USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ignorar"</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">
- <item quantity="one" msgid="8167147081136579439">"Uma correspondência"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Concluído"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Desconectando armazenamento USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Desconectando cartão SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Crie um PIN para modificar restrições"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PINs não coincidem. Tente novamente."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é curto demais. Deve ter pelo menos 4 dígitos."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Tente novamente em 1 segundo"</item>
- <item quantity="other" msgid="4730868920742952817">"Tente novamente em <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Tente novamente em <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ <item quantity="other">Tente novamente em <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Tente novamente mais tarde"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Deslize de cima para baixo para sair da tela inteira"</string>
<string name="done_label" msgid="2093726099505892398">"Concluído"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Para ajudar a melhorar a duração da bateria, o economizador de bateria reduz o desempenho e os limites de vibração do dispositivo, os serviços de localização e a maioria dos dados de segundo plano. E-mail, mensagens e outros aplicativos que dependem de sincronização não podem ser atualizados, a não ser que você os abra.\n\nO economizador de bateria é desligado automaticamente quando o dispositivo está sendo carregado."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Até que seu tempo de inatividade termine"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Por um minuto (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Por %1$d minutos (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Por uma hora (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Por %1$d horas (até às <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Por 1 hora"</item>
- <item quantity="other" msgid="5408537517529822157">"Por %d horas"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Por %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Por %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Por %1$d horas (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Por %1$d horas (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Por %d minutos</item>
+ <item quantity="other">Por %d minutos</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Por %d horas</item>
+ <item quantity="other">Por %d horas</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Recolher"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 29bd05e..f1a11af 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -61,10 +61,11 @@
<string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduceţi codul PUK2 pentru a debloca cardul SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Operațiunea nu a reușit. Activați blocarea cardului SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"V-a mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercare până la blocarea cardului SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"V-au mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercări până la blocarea cardului SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="few">V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări până la blocarea cardului SIM.</item>
+ <item quantity="other">V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> de încercări până la blocarea cardului SIM.</item>
+ <item quantity="one">V-a mai rămas <xliff:g id="NUMBER_0">%d</xliff:g> încercare până la blocarea cardului SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID apelant de primire"</string>
@@ -1131,73 +1132,13 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> doreşte să activeze funcţia Exploraţi prin atingere. Când această funcţie este activată, puteţi auzi sau vedea descrieri pentru ceea ce se află sub degetul dvs. sau puteţi efectua gesturi pentru a interacţiona cu telefonul."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"cu 1 lună în urmă"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Cu mai mult de 1 lună în urmă"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"cu 1 secundă în urmă"</item>
- <item quantity="other" msgid="3903706804349556379">"cu <xliff:g id="COUNT">%d</xliff:g> (de) secunde în urmă"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"cu 1 minut în urmă"</item>
- <item quantity="other" msgid="2176942008915455116">"cu <xliff:g id="COUNT">%d</xliff:g> (de) minute în urmă"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"cu 1 oră în urmă"</item>
- <item quantity="other" msgid="2467273239587587569">"cu <xliff:g id="COUNT">%d</xliff:g> (de) ore în urmă"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="few">Ultimele <xliff:g id="COUNT_1">%d</xliff:g> zile</item>
+ <item quantity="other">Ultimele <xliff:g id="COUNT_1">%d</xliff:g> de zile</item>
+ <item quantity="one">Ultima <xliff:g id="COUNT_0">%d</xliff:g> zi</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Luna trecută"</string>
<string name="older" msgid="5211975022815554840">"Mai vechi"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ieri"</item>
- <item quantity="other" msgid="2479586466153314633">"cu <xliff:g id="COUNT">%d</xliff:g> (de) zile în urmă"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"într-o secundă"</item>
- <item quantity="other" msgid="1241926116443974687">"în <xliff:g id="COUNT">%d</xliff:g> (de) secunde"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"în 1 minut"</item>
- <item quantity="other" msgid="3330713936399448749">"în <xliff:g id="COUNT">%d</xliff:g> (de) minute"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"în 1 oră"</item>
- <item quantity="other" msgid="547290677353727389">"în <xliff:g id="COUNT">%d</xliff:g> (de) ore"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"mâine"</item>
- <item quantity="other" msgid="5109449375100953247">"în <xliff:g id="COUNT">%d</xliff:g> (de) zile"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"cu 1 sec. în urmă"</item>
- <item quantity="other" msgid="3699169366650930415">"cu <xliff:g id="COUNT">%d</xliff:g> (de) secunde în urmă"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"cu 1 min. în urmă"</item>
- <item quantity="other" msgid="851164968597150710">"cu <xliff:g id="COUNT">%d</xliff:g> (de) min. în urmă"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"cu 1 oră în urmă"</item>
- <item quantity="other" msgid="6889970745748538901">"cu <xliff:g id="COUNT">%d</xliff:g> (de) ore în urmă"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ieri"</item>
- <item quantity="other" msgid="3453342639616481191">"cu <xliff:g id="COUNT">%d</xliff:g> (de) zile în urmă"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"în 1 sec."</item>
- <item quantity="other" msgid="5495880108825805108">"în <xliff:g id="COUNT">%d</xliff:g> (de) sec."</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"în 1 min."</item>
- <item quantity="other" msgid="4216113292706568726">"în <xliff:g id="COUNT">%d</xliff:g> (de) min."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"în 1 oră"</item>
- <item quantity="other" msgid="3705373766798013406">"în <xliff:g id="COUNT">%d</xliff:g> (de) ore"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"mâine"</item>
- <item quantity="other" msgid="2973062968038355991">"în <xliff:g id="COUNT">%d</xliff:g> (de) zile"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"pe <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"la <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"în <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1154,21 @@
<string name="weeks" msgid="6509623834583944518">"săptămâni"</string>
<string name="year" msgid="4001118221013892076">"an"</string>
<string name="years" msgid="6881577717993213522">"ani"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"O secundă"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> (de) secunde"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"Un minut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> (de) minute"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"O oră"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> (de) ore"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> secunde</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de secunde</item>
+ <item quantity="one">O secundă</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de minute</item>
+ <item quantity="one">Un minut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> ore</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> de ore</item>
+ <item quantity="one">O oră</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problemă video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Acest fişier video nu este valid pentru a fi transmis în flux către acest dispozitiv."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Nu puteţi reda acest videoclip"</string>
@@ -1333,14 +1277,16 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Niciunul"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de apel"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Ton de apel necunoscut"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Reţea Wi-Fi disponibilă"</item>
- <item quantity="other" msgid="4192424489168397386">"Reţele Wi-Fi disponibile"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Reţea Wi-Fi deschisă disponibilă"</item>
- <item quantity="other" msgid="7915895323644292768">"Reţele Wi-Fi deschise disponibile"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="few">Rețele Wi-Fi disponibile</item>
+ <item quantity="other">Rețele Wi-Fi disponibile</item>
+ <item quantity="one">Rețea Wi-Fi disponibilă</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="few">Rețele Wi-Fi deschise disponibile</item>
+ <item quantity="other">Rețele Wi-Fi deschise disponibile</item>
+ <item quantity="one">Rețea Wi-Fi deschisă disponibilă</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Conectaţi-vă în reţeaua Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Conectaţi-vă la reţea"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1362,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectat ca dispozitiv media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectat ca aparat foto"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectat ca dispozitiv MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectat ca program de instalare"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Conectat la un accesoriu USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Atingeţi pentru alte opţiuni USB."</string>
@@ -1531,10 +1478,11 @@
<string name="skip_button_label" msgid="1275362299471631819">"Omiteţi"</string>
<string name="no_matches" msgid="8129421908915840737">"Nicio potrivire"</string>
<string name="find_on_page" msgid="1946799233822820384">"Găsiţi pe pagină"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 potrivire"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">Un rezultat</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Terminat"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Se demontează stocarea USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Se demontează cardul SD..."</string>
@@ -1820,10 +1768,11 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Creați un cod PIN pentru modificarea restricțiilor"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Codurile PIN nu se potrivesc. Încercați din nou."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Codul PIN este prea scurt. Trebuie să aibă cel puțin 4 cifre."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Reîncercați în 1 sec."</item>
- <item quantity="other" msgid="4730868920742952817">"Reîncercați în <xliff:g id="COUNT">%d</xliff:g> sec."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="few">Reîncercați în <xliff:g id="COUNT">%d</xliff:g> secunde</item>
+ <item quantity="other">Reîncercați în <xliff:g id="COUNT">%d</xliff:g> de secunde</item>
+ <item quantity="one">Reîncercați într-o secundă</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Reîncercați mai târziu"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Glisați în jos pentru a ieși din ecran complet."</string>
<string name="done_label" msgid="2093726099505892398">"Terminat"</string>
@@ -1849,22 +1798,26 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Pentru a îmbunătăți autonomia bateriei, funcția de economisire a energiei reduce performanțele dispozitivului și limitează vibrațiile, serviciile de localizare și majoritatea datelor de fundal. Este posibil ca e-mailurile, mesageria și alte aplicații care depind de sincronizare să nu se actualizeze dacă nu le deschideți.\n\nFuncția de economisire a energiei se dezactivează automat când dispozitivul se încarcă."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Până când inactivitatea dvs. se încheie la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Până la finalizarea perioadei de inactivitate"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Timp de un minut (până la <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Timp de %1$d (de) minute (până la <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Timp de o oră (până la <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Timp de %1$d (de) ore (până la <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item>
- <item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Timp de o oră"</item>
- <item quantity="other" msgid="5408537517529822157">"Timp de %d (de) ore"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="few">Timp de %1$d minute (până la <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Timp de %1$d de minute (până la <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Timp de un minut (până la <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="few">Timp de %1$d ore (până la <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Timp de %1$d de ore (până la <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Timp de o oră (până la <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="few">Timp de %d minute</item>
+ <item quantity="other">Timp de %d de minute</item>
+ <item quantity="one">Timp de un minut</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="few">Timp de %d ore</item>
+ <item quantity="other">Timp de %d de ore</item>
+ <item quantity="one">Timp de o oră</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Nedefinit"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Restrângeți"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a7882b8..94bc21f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"SIM-карта заблокирована с помощью кода PUK. Для разблокировки введите код PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Для разблокировки SIM-карты введите PUK2."</string>
<string name="enablePin" msgid="209412020907207950">"Произошла ошибка. Включите блокировку SIM-карты или карты R-UIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>. После этого SIM-карта будет заблокирована."</item>
- <item quantity="other" msgid="7530597808358774740">"Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>. После этого SIM-карта будет заблокирована."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Осталась <xliff:g id="NUMBER_1">%d</xliff:g> попытка. После этого SIM-карта будет заблокирована.</item>
+ <item quantity="few">Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована.</item>
+ <item quantity="many">Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована.</item>
+ <item quantity="other">Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Идентификация вызывающего абонента"</string>
@@ -1131,73 +1133,14 @@
<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">"Более месяца назад"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 секунду назад"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> с. назад"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 минуту назад"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> мин. назад"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 час назад"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ч. назад"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">За последний <xliff:g id="COUNT_1">%d</xliff:g> день</item>
+ <item quantity="few">За последние <xliff:g id="COUNT_1">%d</xliff:g> дня</item>
+ <item quantity="many">За последние <xliff:g id="COUNT_1">%d</xliff:g> дней</item>
+ <item quantity="other">За последние <xliff:g id="COUNT_1">%d</xliff:g> дня</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Прошлый месяц"</string>
<string name="older" msgid="5211975022815554840">"Еще раньше"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"вчера"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> дн. назад"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"через 1 секунду"</item>
- <item quantity="other" msgid="1241926116443974687">"через <xliff:g id="COUNT">%d</xliff:g> с."</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"через 1 минуту"</item>
- <item quantity="other" msgid="3330713936399448749">"через <xliff:g id="COUNT">%d</xliff:g> мин."</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"через 1 час"</item>
- <item quantity="other" msgid="547290677353727389">"через <xliff:g id="COUNT">%d</xliff:g> ч."</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"завтра"</item>
- <item quantity="other" msgid="5109449375100953247">"через <xliff:g id="COUNT">%d</xliff:g> дн."</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 сек. назад"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> сек. назад"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 мин. назад"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> мин. назад"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 час назад"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ч. назад"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"вчера"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> дн. назад"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"через 1 с."</item>
- <item quantity="other" msgid="5495880108825805108">"через <xliff:g id="COUNT">%d</xliff:g> с."</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"через 1 мин."</item>
- <item quantity="other" msgid="4216113292706568726">"через <xliff:g id="COUNT">%d</xliff:g> мин."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"через 1 час"</item>
- <item quantity="other" msgid="3705373766798013406">"через <xliff:g id="COUNT">%d</xliff:g> ч."</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"завтра"</item>
- <item quantity="other" msgid="2973062968038355991">"через <xliff:g id="COUNT">%d</xliff:g> дн."</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"в <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"в <xliff:g id="YEAR">%s</xliff:g> г."</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"нед."</string>
<string name="year" msgid="4001118221013892076">"г."</string>
<string name="years" msgid="6881577717993213522">"г."</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 сек."</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> сек."</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 мин."</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> мин."</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ч."</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ч."</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> секунда</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> секунды</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> минута</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> минуты</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> минут</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минут</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> час</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> часа</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> часов</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Без звука"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестная мелодия"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Доступна сеть Wi-Fi"</item>
- <item quantity="other" msgid="4192424489168397386">"Доступна сеть Wi-Fi"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Найдена доступная сеть Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"Найдены доступные сети Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Есть доступные сети Wi-Fi</item>
+ <item quantity="few">Есть доступные сети Wi-Fi</item>
+ <item quantity="many">Есть доступные сети Wi-Fi</item>
+ <item quantity="other">Есть доступные сети Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Есть открытые сети Wi-Fi</item>
+ <item quantity="few">Есть открытые сети Wi-Fi</item>
+ <item quantity="many">Есть открытые сети Wi-Fi</item>
+ <item quantity="other">Есть открытые сети Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Подключение к Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Войдите в сеть"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Подключен как устройство хранения данных"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Подключен как камера"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Подключено как MIDI-устройство"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Подключен как установщик"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB-устройство подключено"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Нажмите, чтобы открыть список опций."</string>
@@ -1531,10 +1485,12 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 совпадение"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> из <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> совпадение из <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> совпадения из <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> совпадений из <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> совпадений из <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Отключение USB-накопителя..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Отключение SD-карты..."</string>
@@ -1820,10 +1776,12 @@
<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_too_short" msgid="8173982756265777792">"PIN-код должен содержать не менее 4 символов."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Повтор через 1 сек."</item>
- <item quantity="other" msgid="4730868920742952817">"Повтор через <xliff:g id="COUNT">%d</xliff:g> сек."</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Повторите попытку через <xliff:g id="COUNT">%d</xliff:g> секунду</item>
+ <item quantity="few">Повторите попытку через <xliff:g id="COUNT">%d</xliff:g> секунды</item>
+ <item quantity="many">Повторите попытку через <xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="other">Повторите попытку через <xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Повторите попытку позже."</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Чтобы вернуться в обычный режим, проведите пальцем вниз."</string>
<string name="done_label" msgid="2093726099505892398">"Готово"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Чтобы продлить время работы устройства от батареи, в режиме энергосбережения снижается производительность, а также ограничивается использование вибрации, геолокации и фоновой передачи данных. Данные, требующие синхронизации, могут обновляться только когда вы откроете приложение.\n\nРежим энергосбережения автоматически отключается во время зарядки устройства."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"До отключения режима (в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"До отключения режима"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"На 1 мин. (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"На %1$d мин. (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"На 1 ч. (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"На %1$d ч. (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 мин."</item>
- <item quantity="other" msgid="6924190729213550991">"%d мин."</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 ч."</item>
- <item quantity="other" msgid="5408537517529822157">"%d ч."</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d минута (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d минуты (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d минут (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d минут (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d час (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d часа (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d часов (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d часов (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d минута</item>
+ <item quantity="few">%d минуты</item>
+ <item quantity="many">%d минут</item>
+ <item quantity="other">%d минут</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d час</item>
+ <item quantity="few">%d часа</item>
+ <item quantity="many">%d часов</item>
+ <item quantity="other">%d часов</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Бессрочно"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Свернуть"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index b7ccd99..51493d1 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ඔබගේ SIM පත පතට PUK අගුළු වැටී ඇත. එම අගුල ඇරීමට PUK කේතය ටයිප් කරන්න."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM පතේ අගුළු ඇරීමට PUK2 ටයිප් කරන්න."</string>
<string name="enablePin" msgid="209412020907207950">"අසාර්ථකයි, SIM/RUIM අඟුල සබල කරන්න."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"SIM කාඩ් පත අඟුළු වැටීමට පෙර ඔබ සතුව තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ක් ඉතිරිව ඇත."</item>
- <item quantity="other" msgid="7530597808358774740">"SIM කාඩ් පත අඟුළු වැටීමට පෙර ඔබ සතුව තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ක් ඉතිරිව ඇත."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">ඔබේ SIM කාඩ් පත අඟුළු වැටීමට පෙර තවත් උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ක් ඉතිරිව ඇත.</item>
+ <item quantity="other">ඔබේ SIM කාඩ් පත අඟුළු වැටීමට පෙර තවත් උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ක් ඉතිරිව ඇත.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"පැමිණෙන අමතන්නාගේ ID"</string>
@@ -1133,73 +1133,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"තත්පර 1 කට පෙර"</item>
- <item quantity="other" msgid="3903706804349556379">"තත්පර <xliff:g id="COUNT">%d</xliff:g> ට පෙර"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"මිනිත්තු 1 ට පෙර"</item>
- <item quantity="other" msgid="2176942008915455116">"මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> කට පෙර"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"පැය 1 කට පෙර"</item>
- <item quantity="other" msgid="2467273239587587569">"පැය <xliff:g id="COUNT">%d</xliff:g> කට පෙර"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">අවසන් දින <xliff:g id="COUNT_1">%d</xliff:g></item>
+ <item quantity="other">අවසන් දින <xliff:g id="COUNT_1">%d</xliff:g></item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"අවසාන මාසය"</string>
<string name="older" msgid="5211975022815554840">"පරණ"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"ඊයේ"</item>
- <item quantity="other" msgid="2479586466153314633">"දින <xliff:g id="COUNT">%d</xliff:g> කට පෙර"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"තත්පර 1 කින්"</item>
- <item quantity="other" msgid="1241926116443974687">"තත්පර <xliff:g id="COUNT">%d</xliff:g> කදී"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"මිනිත්තු 1 කදී"</item>
- <item quantity="other" msgid="3330713936399448749">"මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"පැය 1 ක් තුළ"</item>
- <item quantity="other" msgid="547290677353727389">"පැය <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"හෙට"</item>
- <item quantity="other" msgid="5109449375100953247">"දින <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"තත්පර 1 කට පෙර"</item>
- <item quantity="other" msgid="3699169366650930415">"තත්පර <xliff:g id="COUNT">%d</xliff:g> කට පෙර"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"මිනිත්තු 1 කට පෙර"</item>
- <item quantity="other" msgid="851164968597150710">"මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> ට පෙර"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"පැය 1 කට පෙර"</item>
- <item quantity="other" msgid="6889970745748538901">"පැය <xliff:g id="COUNT">%d</xliff:g> ට පෙර"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"ඊයේ"</item>
- <item quantity="other" msgid="3453342639616481191">"දින <xliff:g id="COUNT">%d</xliff:g> ට පෙර"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"තත්පර 1 ක් තුළ"</item>
- <item quantity="other" msgid="5495880108825805108">"තත්පර <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"මිනිත්තු 1 ක් තුළ"</item>
- <item quantity="other" msgid="4216113292706568726">"මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"පැය 1 ක් තුළ"</item>
- <item quantity="other" msgid="3705373766798013406">"පැය <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"හෙට"</item>
- <item quantity="other" msgid="2973062968038355991">"දින <xliff:g id="COUNT">%d</xliff:g> ක් තුළ"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> වන දා"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> ට"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> තුළ"</string>
@@ -1215,18 +1154,18 @@
<string name="weeks" msgid="6509623834583944518">"සති"</string>
<string name="year" msgid="4001118221013892076">"අවුරුද්ද"</string>
<string name="years" msgid="6881577717993213522">"අවුරුදු"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"තත්පර 1"</item>
- <item quantity="other" msgid="1886107766577166786">"තත්පර <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"මිනිත්තු 1"</item>
- <item quantity="other" msgid="3165187169224908775">"මිනිත්තු <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"පැය 1"</item>
- <item quantity="other" msgid="3863962854246773930">"පැය <xliff:g id="COUNT">%d</xliff:g> ක්"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one">තත්පර <xliff:g id="COUNT">%d</xliff:g> යි</item>
+ <item quantity="other">තත්පර <xliff:g id="COUNT">%d</xliff:g> යි</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one">මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> යි</item>
+ <item quantity="other">මිනිත්තු <xliff:g id="COUNT">%d</xliff:g> යි</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one">පැය <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="other">පැය <xliff:g id="COUNT">%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>
@@ -1335,14 +1274,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"කිසිවක් නැත"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"රිගින්ටෝන"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"නොදන්නා රින්ටෝනය"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi ජාලයක් තිබේ"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi ජාල ඇත"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"විවෘත Wi-Fi ජාලය ලබාගත හැක"</item>
- <item quantity="other" msgid="7915895323644292768">"විවෘත Wi-Fi ජාල තිබේ"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Wi-Fi ජාල තිබේ</item>
+ <item quantity="other">Wi-Fi ජාල තිබේ</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">විවෘත Wi-Fi ජාල තිබේ</item>
+ <item quantity="other">විවෘත Wi-Fi ජාල තිබේ</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi ජලයට පුරනය වන්න"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ජාලයට පුරනය වන්න"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1418,6 +1357,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"හරි"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"මාධ්ය උපාංගයක් ලෙස සම්බන්ධිතයි"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"කැමරාවක් ලෙස සම්බන්ධ කර ඇත"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI උපාංගයක් ලෙස සම්බන්ධ වන ලදි"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ස්ථාපිතයක් ලෙස සම්බන්ධයි"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB මෙවලමකට සම්බන්ධිතයි"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"අනෙක් USB විකල්පය සඳහා ස්පර්ශ කරන්න."</string>
@@ -1533,10 +1473,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"ගැළපීම් 1 යි"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> කින් <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> න් <xliff:g id="INDEX">%d</xliff:g> යි</item>
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> න් <xliff:g id="INDEX">%d</xliff:g> යි</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"හරි"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB ආචයනය ගැලවීම..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD පත ගලවමින්..."</string>
@@ -1822,10 +1762,10 @@
<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_too_short" msgid="8173982756265777792">"PIN කුඩා වැඩිය. ඉලක්කම් 4 වත් විය යුතුය."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"තවත් තත්පර 1 කින් යළි උත්සාහ කරන්න"</item>
- <item quantity="other" msgid="4730868920742952817">"තත්පර <xliff:g id="COUNT">%d</xliff:g> කින් නැවත උත්සහ කරන්න"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">තත්පර <xliff:g id="COUNT">%d</xliff:g> කින් නැවත උත්සාහ කරන්න</item>
+ <item quantity="other">තත්පර <xliff:g id="COUNT">%d</xliff:g> කින් නැවත උත්සාහ කරන්න</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"පසුව නැවත උත්සාහ කරන්න"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"උඩ සිට පහළට ස්වයිප් කර පූර්ණ තිරයෙන් ඉවත්වන්න."</string>
<string name="done_label" msgid="2093726099505892398">"අවසන්"</string>
@@ -1851,22 +1791,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"බැටරි ආයු කාලය වැඩිදියුණු කිරීමට උදවු කිරීමට, බැටරි සුරැකුම ඔබේ උපාංගයේ ක්රියාකාරීත්වය අඩුකරන අතර කම්පනය, පිහිටීම් සේවා, සහ බොහෝමයක් පසුබිම් දත්ත සීමා කරයි. ඔබ ඒවා විවෘත නොකරන්නේ නම් මිස ඊමේල්, පණිවිඩකරණය, සහ සමමුහුර්ත කිරීම මත රඳා පවතින වෙනත් යෙදුම් යාවත්කාලීන නොවිය හැකිය.\n\nඔබේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකුම ස්වයංක්රියව අක්රිය වේ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ඔබගේ බිඳවැටුම් වේලාව <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> දී අවසන්වන තුරු"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"ඔබගේ බිදවැටුම් කාලය අවසන් වන තෙක්"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"මිනිත්තු එකක් සඳහා (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> තෙක්)"</item>
- <item quantity="other" msgid="2787867221129368935">"මිනිත්තු %1$d සඳහා (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> තෙක්)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"පැය එකක් සඳහා (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> තෙක්)"</item>
- <item quantity="other" msgid="2827214920627669898">"පැය %1$d සඳහා (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> තෙක්)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"විනාඩි එකක් සඳහා"</item>
- <item quantity="other" msgid="6924190729213550991">"විනාඩි %d සඳහා"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"පැයක් සඳහා"</item>
- <item quantity="other" msgid="5408537517529822157">"පැය %d ක් සඳහා"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">මිනිත්තු %1$d ක් සඳහා (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> තෙක්)</item>
+ <item quantity="other">මිනිත්තු %1$d ක් සඳහා (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> තෙක්)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">පැය %1$d ක් සඳහා (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> තෙක්)</item>
+ <item quantity="other">පැය %1$d ක් සඳහා (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> තෙක්)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">මිනිත්තු %d ක් සඳහා</item>
+ <item quantity="other">මිනිත්තු %d ක් සඳහා</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">පැය %d ක් සඳහා</item>
+ <item quantity="other">පැය %d ක් සඳහා</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> තෙක්"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"අනියත ආකාරයට"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"හකුළන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 2a73770..85ece4f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"Karta SIM je uzamknutá pomocou kódu PUK. Odomknite ju zadaním kódu PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ak chcete odblokovať kartu SIM, zadajte kód PUK2."</string>
<string name="enablePin" msgid="209412020907207950">"Neúspešné, povoľte uzamknutie SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Zostáva vám <xliff:g id="NUMBER">%d</xliff:g> pokus, než sa vaša karta SIM uzamkne."</item>
- <item quantity="other" msgid="7530597808358774740">"Počet zostávajúcich pokusov pred uzamknutím karty SIM: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="few">Zostávajú vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusy, potom sa vaša SIM karta uzamkne.</item>
+ <item quantity="many">Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusu, potom sa vaša SIM karta uzamkne.</item>
+ <item quantity="other">Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusov, potom sa vaša SIM karta uzamkne.</item>
+ <item quantity="one">Zostáva vám <xliff:g id="NUMBER_0">%d</xliff:g> pokus, potom sa vaša SIM karta uzamkne.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Prichádzajúca identifikácia volajúceho"</string>
@@ -1131,73 +1133,14 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Služba <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> požaduje povolenie funkcie Preskúmanie dotykom. Ak je funkcia Preskúmanie dotykom zapnutá, môžete počuť alebo vidieť popisy objektov pod vaším prstom alebo ovládať telefón gestami."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"pred 1 mesiacom"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Viac ako pred 1 mesiacom"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"pred 1 sekundou"</item>
- <item quantity="other" msgid="3903706804349556379">"pred <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Pred minútou"</item>
- <item quantity="other" msgid="2176942008915455116">"pred <xliff:g id="COUNT">%d</xliff:g> minútami"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"pred 1 hodinou"</item>
- <item quantity="other" msgid="2467273239587587569">"pred <xliff:g id="COUNT">%d</xliff:g> hodinami"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="few">Posledné <xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+ <item quantity="many">Posledného <xliff:g id="COUNT_1">%d</xliff:g> dňa</item>
+ <item quantity="other">Posledných <xliff:g id="COUNT_1">%d</xliff:g> dní</item>
+ <item quantity="one">Posledný <xliff:g id="COUNT_0">%d</xliff:g> deň</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Minulý mesiac"</string>
<string name="older" msgid="5211975022815554840">"Staršie"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"včera"</item>
- <item quantity="other" msgid="2479586466153314633">"pred <xliff:g id="COUNT">%d</xliff:g> dňami"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"o 1 sekundu"</item>
- <item quantity="other" msgid="1241926116443974687">"o <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"o 1 minútu"</item>
- <item quantity="other" msgid="3330713936399448749">"o <xliff:g id="COUNT">%d</xliff:g> minút"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"o 1 hodinu"</item>
- <item quantity="other" msgid="547290677353727389">"o <xliff:g id="COUNT">%d</xliff:g> hodín"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"zajtra"</item>
- <item quantity="other" msgid="5109449375100953247">"o <xliff:g id="COUNT">%d</xliff:g> dní"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"pred 1 s"</item>
- <item quantity="other" msgid="3699169366650930415">"pred <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"pred 1 min."</item>
- <item quantity="other" msgid="851164968597150710">"pred <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"pred 1 hodinou"</item>
- <item quantity="other" msgid="6889970745748538901">"pred <xliff:g id="COUNT">%d</xliff:g> hodinami"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"včera"</item>
- <item quantity="other" msgid="3453342639616481191">"pred <xliff:g id="COUNT">%d</xliff:g> dňami"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"o 1 s"</item>
- <item quantity="other" msgid="5495880108825805108">"o <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"o 1 min."</item>
- <item quantity="other" msgid="4216113292706568726">"o <xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"o 1 hodinu"</item>
- <item quantity="other" msgid="3705373766798013406">"o <xliff:g id="COUNT">%d</xliff:g> hodín"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"zajtra"</item>
- <item quantity="other" msgid="2973062968038355991">"o <xliff:g id="COUNT">%d</xliff:g> dní"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"dňa <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"o <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"z <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"týždne"</string>
<string name="year" msgid="4001118221013892076">"rok"</string>
<string name="years" msgid="6881577717993213522">"roky"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 s"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 min."</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min."</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 hod."</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> hod."</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekúnd</item>
+ <item quantity="one">1 sekunda</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minúty</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> minúty</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minút</item>
+ <item quantity="one">1 minúta</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> hodiny</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> hodiny</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> hodín</item>
+ <item quantity="one">1 hodina</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problém s videom"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Je nám ľúto, ale toto video sa nedá streamovať do tohto zariadenia."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Toto video nie je možné prehrať."</string>
@@ -1331,16 +1280,20 @@
<string name="ringtone_default" msgid="3789758980357696936">"Predvolený tón zvonenia"</string>
<string name="ringtone_default_with_actual" msgid="8129563480895990372">"Predvolený tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="7937634392408977062">"Žiadny"</string>
- <string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváňacie tóny"</string>
+ <string name="ringtone_picker_title" msgid="3515143939175119094">"Tóny zvonenia"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Neznámy tón zvonenia"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"K dispozícii je sieť Wi-Fi"</item>
- <item quantity="other" msgid="4192424489168397386">"K dispozícii sú siete Wi-Fi."</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"K dispozícii je verejná sieť Wi-Fi"</item>
- <item quantity="other" msgid="7915895323644292768">"K dispozícii sú verejné siete Wi-Fi"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="few">K dispozícii sú siete Wi-Fi</item>
+ <item quantity="many">K dispozícii sú siete Wi-Fi</item>
+ <item quantity="other">K dispozícii sú siete Wi-Fi</item>
+ <item quantity="one">K dispozícii je sieť Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="few">K dispozícii sú verejné siete Wi-Fi</item>
+ <item quantity="many">K dispozícii sú verejné siete Wi-Fi</item>
+ <item quantity="other">K dispozícii sú verejné siete Wi-Fi</item>
+ <item quantity="one">K dispozícii je verejná sieť Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Prihlásenie sa do siete Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Prihláste sa do siete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pripojené ako mediálne zariadenie"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pripojené ako fotoaparát"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Pripojené ako zariadenie MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pripojené ako inštalátor"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Pripojené k periférnemu zariadeniu USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Dotykom zobrazíte ďalšie možnosti USB."</string>
@@ -1531,10 +1485,12 @@
<string name="skip_button_label" msgid="1275362299471631819">"Preskočiť"</string>
<string name="no_matches" msgid="8129421908915840737">"Žiadne zhody"</string>
<string name="find_on_page" msgid="1946799233822820384">"Vyhľadať na stránke"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"Počet zhôd: 1"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 zápas</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Hotovo"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Prebieha odpájanie úložiska USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Prebieha odpájanie karty SD..."</string>
@@ -1820,10 +1776,12 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Vytvoriť kód PIN pre obmedzenia upravovania"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Kódy PIN sa nezhodujú. Skúste to znova."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Kód PIN je príliš krátky. Musí mať minimálne 4 číslice."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Skúste to zas o 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Skúste to zas o <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="few">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="many">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekundy</item>
+ <item quantity="other">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekúnd</item>
+ <item quantity="one">Skúste to znova o 1 sekundu</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Skúste to znova neskôr"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Režim celej obrazovky ukončíte posunutím nadol."</string>
<string name="done_label" msgid="2093726099505892398">"Hotovo"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Šetrič batérie znižuje výkonnosť vášho zariadenia a obmedzuje vibrovanie, služby určovania polohy a väčšinu údajov na pozadí, aby tak pomohol predĺžiť výdrž batérie. E-mailová aplikácia, aplikácia na odosielanie správ SMS a MMS a ďalšie aplikácie, ktoré sú založené na synchronizácii, sa pravdepodobne aktualizujú až po ich otvorení.\n\nŠetrič batérie sa automaticky vypne, keď zariadenie začnete nabíjať."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dokým o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí výpadok"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Kým skončí vaša odstávka"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Na minútu (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Na %1$d min. (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Na hodinu (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Na %1$d hod. (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item>
- <item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Na 1 h"</item>
- <item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="few">%1$d minúty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d minúty (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d minút (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Minútu (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="few">%1$d hodiny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d hodiny (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d hodín (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Hodinu (do <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="few">%d minúty</item>
+ <item quantity="many">%d minúty</item>
+ <item quantity="other">%d minút</item>
+ <item quantity="one">Minútu</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="few">%d hodiny</item>
+ <item quantity="many">%d hodiny</item>
+ <item quantity="other">%d hodín</item>
+ <item quantity="one">Hodinu</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Natrvalo"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Zbaliť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index bc8a851..320e17a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"Kartica SIM je zaklenjena s kodo PUK. Če jo želite odkleniti, vnesite kodo PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Če želite odstraniti blokiranje kartice SIM, vnesite PUK2."</string>
<string name="enablePin" msgid="209412020907207950">"Ni uspelo. Omogočite zaklepanje kartice SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Na voljo imate še <xliff:g id="NUMBER">%d</xliff:g> poskus. Potem se bo kartica SIM zaklenila."</item>
- <item quantity="other" msgid="7530597808358774740">"Poskusite lahko še <xliff:g id="NUMBER">%d</xliff:g>-krat. Potem se bo kartica SIM zaklenila."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskus. Potem se bo kartica SIM zaklenila.</item>
+ <item quantity="two">Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusa. Potem se bo kartica SIM zaklenila.</item>
+ <item quantity="few">Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskuse. Potem se bo kartica SIM zaklenila.</item>
+ <item quantity="other">Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusov. Potem se bo kartica SIM zaklenila.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID dohodnega klicatelja"</string>
@@ -1131,73 +1133,14 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Storitev <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> želi omogočiti raziskovanje z dotikom. Ko je raziskovanje z dotikom vklopljeno, lahko slišite ali vidite opise tega, kar je pod vašim prstom, ali izvajate poteze za interakcijo s telefonom."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Pred 1 mesecem"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Pred več kot 1 mesecem"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Pred 1 sekundo"</item>
- <item quantity="other" msgid="3903706804349556379">"pred toliko sekundami: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"pred 1 minuto"</item>
- <item quantity="other" msgid="2176942008915455116">"Pred <xliff:g id="COUNT">%d</xliff:g> minutami"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"pred 1 uro"</item>
- <item quantity="other" msgid="2467273239587587569">"Pred <xliff:g id="COUNT">%d</xliff:g> urami"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Zadnji <xliff:g id="COUNT_1">%d</xliff:g> dan</item>
+ <item quantity="two">Zadnja <xliff:g id="COUNT_1">%d</xliff:g> dneva</item>
+ <item quantity="few">Zadnje <xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+ <item quantity="other">Zadnjih <xliff:g id="COUNT_1">%d</xliff:g> dni</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Pretekli mesec"</string>
<string name="older" msgid="5211975022815554840">"Starejše"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"včeraj"</item>
- <item quantity="other" msgid="2479586466153314633">"Pred <xliff:g id="COUNT">%d</xliff:g> dnevi"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"čez 1 sekundo"</item>
- <item quantity="other" msgid="1241926116443974687">"Čez <xliff:g id="COUNT">%d</xliff:g> sekund"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"čez 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"Čez toliko minut: <xliff:g id="COUNT">%d</xliff:g>."</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"čez 1 uro"</item>
- <item quantity="other" msgid="547290677353727389">"čez <xliff:g id="COUNT">%d</xliff:g> ur"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"jutri"</item>
- <item quantity="other" msgid="5109449375100953247">"čez <xliff:g id="COUNT">%d</xliff:g> dni"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"pred 1 sekundo"</item>
- <item quantity="other" msgid="3699169366650930415">"Pred toliko sekundami: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"pred 1 minuto"</item>
- <item quantity="other" msgid="851164968597150710">"Pred <xliff:g id="COUNT">%d</xliff:g> minutami"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"pred 1 uro"</item>
- <item quantity="other" msgid="6889970745748538901">"Pred <xliff:g id="COUNT">%d</xliff:g> urami"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"včeraj"</item>
- <item quantity="other" msgid="3453342639616481191">"Pred <xliff:g id="COUNT">%d</xliff:g> dnevi"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"čez 1 sekundo"</item>
- <item quantity="other" msgid="5495880108825805108">"čez toliko sekund: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"čez 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"čez <xliff:g id="COUNT">%d</xliff:g> minut"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"čez 1 uro"</item>
- <item quantity="other" msgid="3705373766798013406">"čez <xliff:g id="COUNT">%d</xliff:g> ur"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"jutri"</item>
- <item quantity="other" msgid="2973062968038355991">"čez <xliff:g id="COUNT">%d</xliff:g> dni"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"vsak <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ob <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"leta <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"tednov"</string>
<string name="year" msgid="4001118221013892076">"leto"</string>
<string name="years" msgid="6881577717993213522">"let"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekunda"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuta"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> min"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ura"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> h"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> sekunda</item>
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> sekundi</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> sekunde</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minuta</item>
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> minuti</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> minute</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> ura</item>
+ <item quantity="two"><xliff:g id="COUNT">%d</xliff:g> uri</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> ure</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ur</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Težava z videoposnetkom"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ta videoposnetek ni veljaven za pretakanje v to napravo."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Tega videoposnetka ni mogoče predvajati."</string>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Brez"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvonjenja"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Neznana melodija zvonjenja"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Na voljo je brezžično omrežje"</item>
- <item quantity="other" msgid="4192424489168397386">"Na voljo so brezžična omrežja"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Odpiranje razpoložljivega brezžičnega omrežja"</item>
- <item quantity="other" msgid="7915895323644292768">"Odpiranje razpoložljivih brezžičnih omrežij"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Na voljo so omrežja Wi-Fi</item>
+ <item quantity="two">Na voljo so omrežja Wi-Fi</item>
+ <item quantity="few">Na voljo so omrežja Wi-Fi</item>
+ <item quantity="other">Na voljo so omrežja Wi-Fi</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Na voljo so odprta omrežja Wi-Fi</item>
+ <item quantity="two">Na voljo so odprta omrežja Wi-Fi</item>
+ <item quantity="few">Na voljo so odprta omrežja Wi-Fi</item>
+ <item quantity="other">Na voljo so odprta omrežja Wi-Fi</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Prijava v omrežje Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Prijava v omrežje"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"V redu"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Povezan kot predstavnostna naprava"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Povezan kot fotoaparat"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Povezano kot naprava MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Povezan kot namestitveni program"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Priključen na dodatek USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Dotaknite se za prikaz drugih možnosti za USB."</string>
@@ -1531,10 +1485,12 @@
<string name="skip_button_label" msgid="1275362299471631819">"Preskoči"</string>
<string name="no_matches" msgid="8129421908915840737">"Ni ujemanj"</string>
<string name="find_on_page" msgid="1946799233822820384">"Najdi na strani"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 ujemanje"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="two"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Končano"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Izpenjanje pomnilnika USB ..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Izpenjanje kartice SD ..."</string>
@@ -1820,10 +1776,12 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Ustvarite PIN za spreminjanje omejitev"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Kodi PIN se ne ujemata. Poskusite znova."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN je prekratek. Imeti mora vsaj 4 števke."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Poskusite znova čez sekundo"</item>
- <item quantity="other" msgid="4730868920742952817">"Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> s"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> sekundo</item>
+ <item quantity="two">Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> sekundi</item>
+ <item quantity="few">Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> sekunde</item>
+ <item quantity="other">Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> sekund</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Poskusite znova pozneje"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Povlecite z vrha, da zaprete celozaslonski način."</string>
<string name="done_label" msgid="2093726099505892398">"Dokončano"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Varčevanje z energijo akumulatorja podaljša čas njegovega delovanja tako, da zmanjša zmogljivost delovanja naprave in omeji vibriranje, lokacijske storitve ter prenos večine podatkov v ozadju. Aplikacije za e-pošto, sporočanje in drugo, ki uporabljajo sinhroniziranje, se morda ne posodabljajo, razen če jih odprete.\n\nVarčevanje z energijo akumulatorja se samodejno izklopi med polnjenjem akumulatorja naprave."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Do konca prekinitve delovanja ob <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Do konca časa nedelovanja"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Eno minuto (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Toliko minut: %1$d (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Eno uro (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Toliko ur: %1$d (do <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Za eno minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Za %d min"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Za eno uro"</item>
- <item quantity="other" msgid="5408537517529822157">"Za %d h"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%d minuto (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="two">%d minuti (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%d minute (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%d minut (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d uro (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="two">%1$d uri (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d ure (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d ur (do <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d minuto</item>
+ <item quantity="two">%d minuti</item>
+ <item quantity="few">%d minute</item>
+ <item quantity="other">%d minut</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d uro</item>
+ <item quantity="two">%d uri</item>
+ <item quantity="few">%d ure</item>
+ <item quantity="other">%d ur</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Za nedoločen čas"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Strni"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6d1e793..26a436a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -61,10 +61,11 @@
<string name="needPuk" msgid="919668385956251611">"SIM картица је закључана PUK кодом. Унесите PUK кôд да бисте је откључали."</string>
<string name="needPuk2" msgid="4526033371987193070">"Унесите PUK2 да бисте деблокирали SIM картицу."</string>
<string name="enablePin" msgid="209412020907207950">"Није успело. Омогућите закључавање SIM/RUIM картице."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Имате још <xliff:g id="NUMBER">%d</xliff:g> покушај пре него што се SIM картица закључа."</item>
- <item quantity="other" msgid="7530597808358774740">"Имате још <xliff:g id="NUMBER">%d</xliff:g> покушаја пре него што се SIM картица закључа."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај пре него што се SIM картица закључа.</item>
+ <item quantity="few">Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја пре него што се SIM картица закључа.</item>
+ <item quantity="other">Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја пре него што се SIM картица закључа.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Долазни ИД позиваоца"</string>
@@ -1131,73 +1132,13 @@
<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">"Пре месец дана"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Пре месец дана"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Пре 1 секунде"</item>
- <item quantity="other" msgid="3903706804349556379">"пре <xliff:g id="COUNT">%d</xliff:g> секунде(и)"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Пре једног минута"</item>
- <item quantity="other" msgid="2176942008915455116">"пре <xliff:g id="COUNT">%d</xliff:g> минута"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Пре сат времена"</item>
- <item quantity="other" msgid="2467273239587587569">"пре <xliff:g id="COUNT">%d</xliff:g> сата(и)"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Претходни <xliff:g id="COUNT_1">%d</xliff:g> дан</item>
+ <item quantity="few">Претходна <xliff:g id="COUNT_1">%d</xliff:g> дана</item>
+ <item quantity="other">Претходних <xliff:g id="COUNT_1">%d</xliff:g> дана</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Прошлог месеца"</string>
<string name="older" msgid="5211975022815554840">"Старије"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"јуче"</item>
- <item quantity="other" msgid="2479586466153314633">"пре <xliff:g id="COUNT">%d</xliff:g> дана"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"за 1 секунду"</item>
- <item quantity="other" msgid="1241926116443974687">"за <xliff:g id="COUNT">%d</xliff:g> секунде(и)"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"за 1 минут"</item>
- <item quantity="other" msgid="3330713936399448749">"за <xliff:g id="COUNT">%d</xliff:g> минута"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"за 1 сат"</item>
- <item quantity="other" msgid="547290677353727389">"за <xliff:g id="COUNT">%d</xliff:g> сата(и)"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"сутра"</item>
- <item quantity="other" msgid="5109449375100953247">"за <xliff:g id="COUNT">%d</xliff:g> дана"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Пре једне сек"</item>
- <item quantity="other" msgid="3699169366650930415">"пре <xliff:g id="COUNT">%d</xliff:g> сек"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Пре један мин"</item>
- <item quantity="other" msgid="851164968597150710">"пре <xliff:g id="COUNT">%d</xliff:g> мин"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Пре сат времена"</item>
- <item quantity="other" msgid="6889970745748538901">"пре <xliff:g id="COUNT">%d</xliff:g> сата(и)"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"јуче"</item>
- <item quantity="other" msgid="3453342639616481191">"пре <xliff:g id="COUNT">%d</xliff:g> дана"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"за 1 сек"</item>
- <item quantity="other" msgid="5495880108825805108">"за <xliff:g id="COUNT">%d</xliff:g> сек"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"за 1 мин"</item>
- <item quantity="other" msgid="4216113292706568726">"за <xliff:g id="COUNT">%d</xliff:g> мин"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"за 1 сат"</item>
- <item quantity="other" msgid="3705373766798013406">"за <xliff:g id="COUNT">%d</xliff:g> сата(и)"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"сутра"</item>
- <item quantity="other" msgid="2973062968038355991">"за <xliff:g id="COUNT">%d</xliff:g> дана"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"дана <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"у <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"у <xliff:g id="YEAR">%s</xliff:g>."</string>
@@ -1213,18 +1154,21 @@
<string name="weeks" msgid="6509623834583944518">"недеље(а)"</string>
<string name="year" msgid="4001118221013892076">"година"</string>
<string name="years" msgid="6881577717993213522">"годинe(а)"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 секунда"</item>
- <item quantity="other" msgid="1886107766577166786">"Секунди: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 минут"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> минута"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 сат"</item>
- <item quantity="other" msgid="3863962854246773930">"Сати: <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> секунда</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> секунде</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> минут</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> минута</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> минута</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> сат</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> сата</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1277,16 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Без"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Звукови звона"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Непознати звук звона"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Доступне су Wi-Fi мреже"</item>
- <item quantity="other" msgid="4192424489168397386">"Доступне Wi-Fi мреже"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Доступна је отворена Wi-Fi мрежа"</item>
- <item quantity="other" msgid="7915895323644292768">"Доступне су отворене Wi-Fi мреже"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Wi-Fi мреже су доступне</item>
+ <item quantity="few">Wi-Fi мреже су доступне</item>
+ <item quantity="other">Wi-Fi мреже су доступне</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Отворене Wi-Fi мреже су доступне</item>
+ <item quantity="few">Отворене Wi-Fi мреже су доступне</item>
+ <item quantity="other">Отворене Wi-Fi мреже су доступне</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Пријавите се на Wi-Fi мрежу"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Пријављивање на мрежу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1362,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Потврди"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Повезан као медијски уређај"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Повезан као камера"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Повезано је као MIDI уређај"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Повезан као инсталациони програм"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Повезано са USB додатком"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Додирните за друге опције USB-а."</string>
@@ -1531,10 +1478,11 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 подударање"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Искључивање USB меморије..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Искључивање SD картице..."</string>
@@ -1820,10 +1768,11 @@
<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_too_short" msgid="8173982756265777792">"PIN је прекратак. Мора да садржи најмање 4 цифре."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Покушајте опет за 1 сек"</item>
- <item quantity="other" msgid="4730868920742952817">"Покушајте опет за <xliff:g id="COUNT">%d</xliff:g> сек"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунду</item>
+ <item quantity="few">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунде</item>
+ <item quantity="other">Покушајте поново за <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Покушајте поново касније"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Превуците прстом одозго надоле да бисте изашли из целог екрана."</string>
<string name="done_label" msgid="2093726099505892398">"Готово"</string>
@@ -1849,22 +1798,26 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Да би продужила време трајања батерије, уштеда батерије смањује перформансе уређаја и ограничава вибрацију, услуге локације и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију можда неће да се ажурирају ако их не отворите.\n\nУштеда батерије се аутоматски искључује када се уређај пуни."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Док се прекид рада не заврши у <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Док се време одмора не заврши"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Један минут (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d минута (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Један сат (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d сата(и) (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Један минут"</item>
- <item quantity="other" msgid="6924190729213550991">"%d мин"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Један сат"</item>
- <item quantity="other" msgid="5408537517529822157">"%d с"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d минут (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d минута (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d минута (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d сат (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d сата (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d сати (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d минут</item>
+ <item quantity="few">%d минута</item>
+ <item quantity="other">%d минута</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d сат</item>
+ <item quantity="few">%d сата</item>
+ <item quantity="other">%d сати</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Бесконачно"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Скупи"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 61b0a3d..1457940 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Ditt SIM-kort är PUK-låst. Ange PUK-koden om du vill låsa upp det."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ange PUK2-koden för att häva spärren av SIM-kortet."</string>
<string name="enablePin" msgid="209412020907207950">"Försöket misslyckades. Aktivera SIM-/RUIM-lås."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Du har <xliff:g id="NUMBER">%d</xliff:g> försök kvar innan SIM-kortet låses."</item>
- <item quantity="other" msgid="7530597808358774740">"Du har <xliff:g id="NUMBER">%d</xliff:g> försök kvar innan SIM-kortet låses."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Du har <xliff:g id="NUMBER_1">%d</xliff:g> försök kvar innan SIM-kortet låses.</item>
+ <item quantity="one">Du har <xliff:g id="NUMBER_0">%d</xliff:g> försök kvar innan SIM-kortet låses.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI-kod"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Nummerpresentatör för inkommande samtal"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill aktivera Explore by Touch. När funktionen är aktiv kan du höra eller se beskrivningar av vad du har under fingret eller utföra gester för att göra saker med telefonen."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"för 1 månad sedan"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"För mer än en månad sedan"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"för 1 sekund sedan"</item>
- <item quantity="other" msgid="3903706804349556379">"för <xliff:g id="COUNT">%d</xliff:g> sekunder sedan"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"för 1 minut sedan"</item>
- <item quantity="other" msgid="2176942008915455116">"för <xliff:g id="COUNT">%d</xliff:g> minuter sedan"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"för 1 timme sedan"</item>
- <item quantity="other" msgid="2467273239587587569">"för <xliff:g id="COUNT">%d</xliff:g> timmar sedan"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">De senaste <xliff:g id="COUNT_1">%d</xliff:g> dagarna</item>
+ <item quantity="one">Den senaste dagen (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Föregående månad"</string>
<string name="older" msgid="5211975022815554840">"Äldre"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"igår"</item>
- <item quantity="other" msgid="2479586466153314633">"för <xliff:g id="COUNT">%d</xliff:g> dagar sedan"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"om 1 sekund"</item>
- <item quantity="other" msgid="1241926116443974687">"om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"om 1 minut"</item>
- <item quantity="other" msgid="3330713936399448749">"om <xliff:g id="COUNT">%d</xliff:g> minuter"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"om 1 timme"</item>
- <item quantity="other" msgid="547290677353727389">"om <xliff:g id="COUNT">%d</xliff:g> timmar"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"imorgon"</item>
- <item quantity="other" msgid="5109449375100953247">"om <xliff:g id="COUNT">%d</xliff:g> dagar"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"för 1 sek sedan"</item>
- <item quantity="other" msgid="3699169366650930415">"för <xliff:g id="COUNT">%d</xliff:g> sekunder sedan"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"för 1 minut sedan"</item>
- <item quantity="other" msgid="851164968597150710">"för <xliff:g id="COUNT">%d</xliff:g> minuter sedan"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"för 1 timme sedan"</item>
- <item quantity="other" msgid="6889970745748538901">"för <xliff:g id="COUNT">%d</xliff:g> timmar sedan"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"igår"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> dagar sedan"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"om 1 sekund"</item>
- <item quantity="other" msgid="5495880108825805108">"om <xliff:g id="COUNT">%d</xliff:g> sek"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"om 1 minut"</item>
- <item quantity="other" msgid="4216113292706568726">"om <xliff:g id="COUNT">%d</xliff:g> minuter"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"om 1 timme"</item>
- <item quantity="other" msgid="3705373766798013406">"om <xliff:g id="COUNT">%d</xliff:g> timmar"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"imorgon"</item>
- <item quantity="other" msgid="2973062968038355991">"om <xliff:g id="COUNT">%d</xliff:g> dagar"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"den <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"kl. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"veckor"</string>
<string name="year" msgid="4001118221013892076">"år"</string>
<string name="years" msgid="6881577717993213522">"år"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 sekund"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minut"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> minuter"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 timme"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> timmar"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="one">1 sekund</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> minuter</item>
+ <item quantity="one">1 minut</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> timmar</item>
+ <item quantity="one">1 timme</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Videoproblem"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Videon kan tyvärr inte spelas upp i den här enheten."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Det går inte att spela upp videon."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Ringsignaler"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Okänd ringsignal"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi-nätverk är tillgängliga"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi-nätverk är tillgängliga"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
- <item quantity="other" msgid="7915895323644292768">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi-nätverk är tillgängliga</item>
+ <item quantity="one">Wi-Fi-nätverk är tillgängligt</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Öppna Wi-Fi-nätverk är tillgängliga</item>
+ <item quantity="one">Öppet Wi-Fi-nätverk är tillgängligt</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Logga in på Wi-Fi-nätverk"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ansluten som en mediaenhet"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ansluten som en kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Ansluten som en MIDI-enhet"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ansluten som installationsprogram"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ansluten till ett USB-tillbehör"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Tryck om du vill visa andra USB-alternativ."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Hoppa över"</string>
<string name="no_matches" msgid="8129421908915840737">"Inga träffar"</string>
<string name="find_on_page" msgid="1946799233822820384">"Sök på sidan"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 träff"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> av <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 träff</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Klar"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Monterar bort USB-lagringsenhet ..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Monterar bort SD-kort ..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Skapa en pinkod om du vill ändra begränsningar"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Pinkoderna stämmer inte överens. Försök igen."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Pinkoden är för kort. Måste vara minst fyra siffror."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Försök igen om en sekund"</item>
- <item quantity="other" msgid="4730868920742952817">"Försök igen om <xliff:g id="COUNT">%d</xliff:g> sekunder"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Försök igen om <xliff:g id="COUNT">%d</xliff:g> sekunder</item>
+ <item quantity="one">Försök igen om en sekund</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Försök igen senare"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Dra nedåt om du vill avbryta fullskärmsläget."</string>
<string name="done_label" msgid="2093726099505892398">"Klart"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"I batterisparläget reduceras enhetens prestanda så att batteriet ska räcka längre och vibration, platstjänster samt den mesta användningen av bakgrundsdata begränsas. Det kan hända att appar för e-post, sms och annat som kräver synkronisering inte uppdateras förrän du öppnar dem.\n\nBatterisparläget inaktiveras automatiskt när enheten laddas."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Tills avbrottstiden är slut <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Tills avbrottstiden är slut"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"I en minut (till kl. <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"I %1$d minuter (till kl. <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"I en timme (till kl. <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"I %1$d timmar (till kl. <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"I en minut"</item>
- <item quantity="other" msgid="6924190729213550991">"I %d minuter"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"I en timme"</item>
- <item quantity="other" msgid="5408537517529822157">"I %d timmar"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">I %1$d minuter (till kl. <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">I en minut (till kl. <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">I %1$d timmar (till kl. <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">I en timme (till kl. <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">I %d minuter</item>
+ <item quantity="one">I en minut</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">I %d timmar</item>
+ <item quantity="one">I en timme</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"För alltid"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Komprimera"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 9a97e24..f135f7a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Kadi yako ya SIM imefungwa na PUK. Anika msimbo wa PUK ili kuifungua."</string>
<string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua SIM kadi."</string>
<string name="enablePin" msgid="209412020907207950">"Imeshindwa, washa ufungaji wa SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g> kabla ya SIM kufungwa."</item>
- <item quantity="other" msgid="7530597808358774740">"Umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g> kabla ya SIM kufungwa."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Umebakisha majaribio <xliff:g id="NUMBER_1">%d</xliff:g> kabla SIM haijafungwa.</item>
+ <item quantity="one">Umebakisha majaribio <xliff:g id="NUMBER_0">%d</xliff:g> kabla SIM haijafungwa.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Kitambulisho cha Mpigaji wa Simu Inayoingia"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> inataka kuwezesha Kuchunguza kwa Kugusa. Wakati Kuchunguza kwa Kugusa kumewezeshwa, unaweza kusikia au kuona maelezo ya kilicho chini ya kidole chako au kutumia ishara ili kuingiliana na simu."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"Mwezi 1 uliopita"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Kabla ya mwezi 1 uliopita"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"Sekunde 1 iliopita"</item>
- <item quantity="other" msgid="3903706804349556379">"sekunde <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"Dakika 1 iliyopita"</item>
- <item quantity="other" msgid="2176942008915455116">"Dakika <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"Saa 1 iliyopita"</item>
- <item quantity="other" msgid="2467273239587587569">"Saa <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Siku <xliff:g id="COUNT_1">%d</xliff:g> zilizopita</item>
+ <item quantity="one">Siku <xliff:g id="COUNT_0">%d</xliff:g> iliyopita</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Mwezi uliopita"</string>
<string name="older" msgid="5211975022815554840">"Kuukuu zaidi"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"jana"</item>
- <item quantity="other" msgid="2479586466153314633">"siku <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"kati ya sekunde 1"</item>
- <item quantity="other" msgid="1241926116443974687">"kati ya sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"kati ya dakika 1"</item>
- <item quantity="other" msgid="3330713936399448749">"baada ya dakika <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"kati ya saa 1"</item>
- <item quantity="other" msgid="547290677353727389">"kati ya saa <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"kesho"</item>
- <item quantity="other" msgid="5109449375100953247">"katika siku <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"Sekunde 1 iliyopita"</item>
- <item quantity="other" msgid="3699169366650930415">"Sekunde <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"Dakika 1 iliyopita"</item>
- <item quantity="other" msgid="851164968597150710">"Dakika <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"Saa 1 iliyopita"</item>
- <item quantity="other" msgid="6889970745748538901">"Saa <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"jana"</item>
- <item quantity="other" msgid="3453342639616481191">"siku <xliff:g id="COUNT">%d</xliff:g> zilizopita"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"kati ya sekunde 1"</item>
- <item quantity="other" msgid="5495880108825805108">"kati ya sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"baada ya dakika 1"</item>
- <item quantity="other" msgid="4216113292706568726">"kati ya dakika<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"kati ya saa 1"</item>
- <item quantity="other" msgid="3705373766798013406">"katika saa <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"kesho"</item>
- <item quantity="other" msgid="2973062968038355991">"kati ya siku <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"tarehe <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"Saa <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ndani ya <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"wiki"</string>
<string name="year" msgid="4001118221013892076">"mwaka"</string>
<string name="years" msgid="6881577717993213522">"miaka"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"Sekunde 1"</item>
- <item quantity="other" msgid="1886107766577166786">"Sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"Dakika 1"</item>
- <item quantity="other" msgid="3165187169224908775">"Dakika <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"Saa 1"</item>
- <item quantity="other" msgid="3863962854246773930">"Saa <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other">Sekunde <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="one">Sekunde 1</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other">Dakika <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="one">Dakika 1</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other">Saa <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="one">Saa 1</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Shida ya video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video hii si halali kutiririshwa kwa kifaa hiki."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Haiwezi kucheza video hii."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Hamna"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Toni za mlio"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Mlio amabo haujulikani"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Mtandao wa Wi-Fi unapatikana"</item>
- <item quantity="other" msgid="4192424489168397386">"Mitandao ya Wi-Fi inapatikana"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Fungua mtandao wa Wi-Fi unaopatikana"</item>
- <item quantity="other" msgid="7915895323644292768">"Fungua mitandao ya Wi-Fi inayopatikana"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Mitandao ya Wi-Fi inapatikana</item>
+ <item quantity="one">Mtandao wa Wi-Fi unapatikana</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Fungua mitandao ya Wi-Fi inayopatikana</item>
+ <item quantity="one">Fungua mtandao wa Wi-Fi unaopatikana</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Ingia kwenye mtandao wa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Ingia kwenye mtandao"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Sawa"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Imeunganishwa kama kifaa cha midia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Imeunganishwa kama kamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Kimeunganishwa kama kifaa cha MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Imeunganishwa kama kisakinishi"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Imeunganishwa kwa kifuasi cha USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Gusa ili uone chaguo zingine za USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Ruka"</string>
<string name="no_matches" msgid="8129421908915840737">"Hakuna vinavyolingana"</string>
<string name="find_on_page" msgid="1946799233822820384">"Pata kwenye ukurasa"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"Linganisho 1"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ya <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> kati ya <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 inayolingana</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Nimemaliza"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Inaondoa hifadhi ya USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Inaondoa kadi ya SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Unda PIN ya kurekebisha vikwazo"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN hazilingani. Jaribu tena."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ni fupi mno. Lazima iwe angalau tarakimu 4."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Jaribu tena baada ya sekunde 1"</item>
- <item quantity="other" msgid="4730868920742952817">"Jaribu tena baada ya sekunde <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Jaribu tena baada ya sekunde <xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="one">Jaribu tena baada ya sekunde 1</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Jaribu tena baadaye"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Telezesha kidole kwa kasi chini kuanzia juu ili uondoke kwenye skrini zima."</string>
<string name="done_label" msgid="2093726099505892398">"Imekamilika"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Kusaidia kuboresha muda wa matumizi ya betri, inayookoa betri hupunguza utendaji wa kifaa chako na kupunguza mtetemo, huduma za utambuzi wa mahali, na data nyingi ya chini chini. Barua pepe, ujumbe na programu nyingine zinazotege,ea usawazishaji huenda zisisasishwe usipozifungua.\n\nInayookoa betri hujizima kiotomatiki kifaa chako kinapokuwa kinachaji."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> wakati wa kutotenda kazi kwa kifaa chako unapoisha"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Hadi muda wako wa hali tuli utakapoisha"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Kwa dakika moja (hadi <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Kwa dakika %1$d (hadi <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Kwa saa moja (hadi <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Kwa saa %1$d (hadi <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item>
- <item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Kwa saa moja"</item>
- <item quantity="other" msgid="5408537517529822157">"Kwa saa %d"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Kwa dakika %1$d (hadi <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Kwa dakika moja (hadi <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Kwa saa %1$d (hadi <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Kwa saa moja (hadi <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Kwa dakika %d</item>
+ <item quantity="one">Kwa dakika moja</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Kwa saa %d</item>
+ <item quantity="one">Kwa saa moja</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Bila kikomo"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Kunja"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 03ffc98..07336d4 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"உங்கள் சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
<string name="needPuk2" msgid="4526033371987193070">"சிம் கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
<string name="enablePin" msgid="209412020907207950">"தோல்வி, சிம்/RUIM பூட்டை இயக்கவும்."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- <item quantity="other" msgid="7530597808358774740">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயற்சிக்கலாம்.</item>
+ <item quantity="one">சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER_0">%d</xliff:g> முறை முயற்சிக்கலாம்.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"உள்வரும் அழைப்பாளர் ஐடி"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 வினாடிக்கு முன்பு"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகளுக்கு முன்பு"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 நிமிடம் முன்பு"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> நிமிடத்திற்கு முன்"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 மணிநேரம் முன்பு"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரத்திற்கு முன்பு"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">கடந்த <xliff:g id="COUNT_1">%d</xliff:g> நாட்களில்</item>
+ <item quantity="one">கடந்த <xliff:g id="COUNT_0">%d</xliff:g> நாளில்</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"சென்ற மாதம்"</string>
<string name="older" msgid="5211975022815554840">"பழையது"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"நேற்று"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> நாட்களுக்கு முன்பு"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 வினாடியில்"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகளில்"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 நிமிடத்தில்"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> நிமிடங்களில்"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 மணிநேரத்தில்"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரத்தில்"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"நாளை"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> நாட்களில்"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 வினாடி முன்பு"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகளுக்கு முன்பு"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 நிமிடம் முன்பு"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> நிமிடத்திற்கு முன்"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 மணிநேரம் முன்பு"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரத்திற்கு முன்பு"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"நேற்று"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> நாட்களுக்கு முன்பு"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 வினாடியில்"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகளில்"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 நிமிடத்தில்"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> நிமிடங்களில்"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 மணிநேரத்தில்"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரத்தில்"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"நாளை"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> நாட்களில்"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> அன்று"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> இல்"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> இல்"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"வாரங்கள்"</string>
<string name="year" msgid="4001118221013892076">"ஆண்டு"</string>
<string name="years" msgid="6881577717993213522">"ஆண்டுகள்"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 வினாடி"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகள்"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 நிமிடம்"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> நிமிடங்கள்"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 மணிநேரம்"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> மணிநேரம்"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> வினாடிகள்</item>
+ <item quantity="one">1 வினாடி</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> நிமிடங்கள்</item>
+ <item quantity="one">1 நிமிடம்</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> மணிநேரம்</item>
+ <item quantity="one">1 மணிநேரம்</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ஏதுமில்லை"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"ரிங்டோன்கள்"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"அறியப்படாத ரிங்டோன்"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"வைஃபை நெட்வொர்க் உள்ளது"</item>
- <item quantity="other" msgid="4192424489168397386">"வைஃபை நெட்வொர்க்குகள் உள்ளன"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"இருக்கும் வைஃபை நெட்வொர்க்கைத் திற"</item>
- <item quantity="other" msgid="7915895323644292768">"இருக்கும் வைஃபை நெட்வொர்க்குகளைத் திற"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
+ <item quantity="one">வைஃபை நெட்வொர்க் உள்ளது</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">பொது வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
+ <item quantity="one">பொது வைஃபை நெட்வொர்க் உள்ளது</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"வைஃபை நெட்வொர்க்கில் உள்நுழையவும்"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"நெட்வொர்க்கில் உள்நுழையவும்"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"சரி"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"மீடியா சாதனமாக இணைக்கப்பட்டது"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"கேமராவாக இணைக்கப்பட்டுள்ளது"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI சாதனமாக இணைக்கப்பட்டது"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"நிறுவியாக இணைக்கப்பட்டது"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB துணைக்கருவியுடன் இணைக்கப்பட்டுள்ளது"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"மற்ற USB விருப்பங்களுக்குத் தொடவும்."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 பொருத்தம்"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g> இல் <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> / <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 பொருத்தம்</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"முடிந்தது"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB சேமிப்பிடத்தை இணைப்பு நீக்குகிறது…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD கார்டை இணைப்பு நீக்குகிறது…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு பின்னை உருவாக்கவும்"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINகள் பொருந்தவில்லை. மீண்டும் முயற்சிக்கவும்."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"பின் மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 வினாடி கழித்து முயற்சிக்கவும்"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்</item>
+ <item quantity="one">1 வினாடி கழித்து முயற்சிக்கவும்</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"மீண்டும் முயற்சிக்கவும்"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"முழுத் திரையிலிருந்து வெளியேற மேலிருந்து கீழே ஸ்வைப் செய்யவும்."</string>
<string name="done_label" msgid="2093726099505892398">"முடிந்தது"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"பேட்டரி ஆயுளை மேம்படுத்த, பேட்டரி சேமிப்பான் உங்கள் சாதனத்தின் செயல்திறனைக் குறைத்து, அதிர்வு, இடச் சேவைகள் மற்றும் பெரும்பாலான பின்புலத் தரவு போன்றவற்றைக் கட்டுப்படுத்துகிறது. ஒத்திசைவைச் சார்ந்துள்ள மின்னஞ்சல், செய்தியிடல் மற்றும் பிற பயன்பாடுகளானது அவற்றைத் திறக்கும்வரையில் புதுப்பிக்கப்படாமல் போகக்கூடும்.\n\nஉங்கள் ஃபோன் சார்ஜ் செய்யப்படும்போது, பேட்டரி சேமிப்பான் தானாகவே முடங்கும்."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> முடியும் வரை"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"செயலற்ற நேரம் முடியும் வரை"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ஒரு நிமிடத்திற்கு (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> வரை)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d நிமிடங்களுக்கு (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> வரை)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ஒரு மணிநேரத்திற்கு (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> வரை)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d மணிநேரத்திற்கு (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> வரை)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ஒரு நிமிடம்"</item>
- <item quantity="other" msgid="6924190729213550991">"%d நிமிடங்கள்"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ஒரு மணி நேரம்"</item>
- <item quantity="other" msgid="5408537517529822157">"%d மணிநேரம்"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d நிமிடங்களுக்கு (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> வரை)</item>
+ <item quantity="one">ஒரு நிமிடத்திற்கு (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> வரை)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d மணிநேரத்திற்கு (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> வரை)</item>
+ <item quantity="one">ஒரு மணிநேரத்திற்கு (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> வரை)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d நிமிடங்களுக்கு</item>
+ <item quantity="one">ஒரு நிமிடத்திற்கு</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d மணிநேரத்திற்கு</item>
+ <item quantity="one">ஒரு மணிநேரத்திற்கு</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> வரை"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"வரையறையற்றது"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"சுருக்கு"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 2c80adb..1767ce2 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"మీ సిమ్ కార్డు PUK-లాక్ చేయబడింది. దీన్ని అన్లాక్ చేయడానికి PUK కోడ్ను టైప్ చేయండి."</string>
<string name="needPuk2" msgid="4526033371987193070">"సిమ్ కార్డును అన్బ్లాక్ చేయడానికి PUK2ని టైప్ చేయండి."</string>
<string name="enablePin" msgid="209412020907207950">"వైఫల్యం, సిమ్/RUIM లాక్ను ప్రారంభించండి."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"సిమ్ లాక్ కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది."</item>
- <item quantity="other" msgid="7530597808358774740">"సిమ్ లాక్ కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">SIM లాక్ కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి.</item>
+ <item quantity="one">SIM లాక్ కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ఇన్కమింగ్ కాలర్ ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 సెకను క్రితం"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> సెకన్ల క్రితం"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 నిమిషం క్రితం"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> నిమిషాల క్రితం"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 గంట క్రితం"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> గంటల క్రితం"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">గత <xliff:g id="COUNT_1">%d</xliff:g> రోజులు</item>
+ <item quantity="one">గత <xliff:g id="COUNT_0">%d</xliff:g> రోజు</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"గత నెల"</string>
<string name="older" msgid="5211975022815554840">"పాతది"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"నిన్న"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> రోజుల క్రితం"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 సెకనులో"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> సెకన్లలో"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 నిమిషంలో"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> నిమిషాల్లో"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 గంటలో"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> గంటల్లో"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"రేపు"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> రోజుల్లో"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 సెక క్రితం"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> సెక క్రితం"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 నిమి క్రితం"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> నిమి క్రితం"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 గంట క్రితం"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> గంటల క్రితం"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"నిన్న"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> రోజుల క్రితం"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 సెకనులో"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> సెకన్లలో"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 నిమిషంలో"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> నిమిషాల్లో"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 గంటలో"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> గంటల్లో"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"రేపు"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> రోజుల్లో"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>న"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>కి"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>లో"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"వారాలు"</string>
<string name="year" msgid="4001118221013892076">"సంవత్సరం"</string>
<string name="years" msgid="6881577717993213522">"సంవత్సరాలు"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 సెకను"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> సెకన్లు"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 నిమిషం"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> నిమిషాలు"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 గంట"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> గంటలు"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> సెకన్లు</item>
+ <item quantity="one">1 సెకను</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> నిమిషాలు</item>
+ <item quantity="one">1 నిమిషం</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> గంటలు</item>
+ <item quantity="one">1 గంట</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ఏదీ వద్దు"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"రింగ్టోన్లు"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"తెలియని రింగ్టోన్"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi నెట్వర్క్లు అందుబాటులో ఉన్నాయి"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"అందుబాటులో ఉన్న Wi-Fi నెట్వర్క్ను తెరవండి"</item>
- <item quantity="other" msgid="7915895323644292768">"అందుబాటులో ఉన్న Wi-Fi నెట్వర్క్లను తెరవండి"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi నెట్వర్క్లు అందుబాటులో ఉన్నాయి</item>
+ <item quantity="one">Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">ఓపెన్ Wi-Fi నెట్వర్క్లు అందుబాటులో ఉన్నాయి</item>
+ <item quantity="one">ఓపెన్ Wi-Fi నెట్వర్క్ అందుబాటులో ఉంది</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi నెట్వర్క్కు సైన్ ఇన్ చేయండి"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"నెట్వర్క్కు సైన్ ఇన్ చేయండి"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"సరే"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"మీడియా పరికరంగా కనెక్ట్ చేయబడింది"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"కెమెరాగా కనెక్ట్ చేయబడింది"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI పరికరం వలె కనెక్ట్ చేయబడింది"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ఇన్స్టాలర్గా కనెక్ట్ చేయబడింది"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB ఉపకరణానికి కనెక్ట్ చేయబడింది"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"ఇతర USB ఎంపికల కోసం తాకండి."</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 సరిపోలిక"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>లో <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>లో <xliff:g id="INDEX">%d</xliff:g></item>
+ <item quantity="one">1 సరిపోలిక</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"పూర్తయింది"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB నిల్వను అన్మౌంట్ చేస్తోంది…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD కార్డును అన్మౌంట్ చేస్తోంది…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"నియంత్రణలను సవరించడానికి పిన్ను రూపొందించండి"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINలు సరిపోలలేదు. మళ్లీ ప్రయత్నించండి."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"పిన్ చాలా చిన్నదిగా ఉంది. తప్పనిసరిగా కనీసం 4 అంకెలు ఉండాలి."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 సెకనులో మళ్లీ ప్రయత్నించండి"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి</item>
+ <item quantity="one">1 సెకనులో మళ్లీ ప్రయత్నించండి</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"తర్వాత మళ్లీ ప్రయత్నించండి"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"పూర్తి స్క్రీన్ నుండి నిష్క్రమించడానికి పైనుండి కిందికి స్వైప్ చేయండి."</string>
<string name="done_label" msgid="2093726099505892398">"పూర్తయింది"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"బ్యాటరీ జీవితకాలాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరును తగ్గిస్తుంది మరియు వైబ్రేషన్ను, స్థాన సేవలను మరియు ఎక్కువ నేపథ్య డేటాను పరిమితం చేస్తుంది. ఇమెయిల్, మెసేజింగ్ మరియు సమకాలీకరణపై ఆధారపడే ఇతర అనువర్తనాలు మీరు వాటిని తెరిస్తే మినహా నవీకరించబడవు.\n\nమీ పరికరం ఛార్జ్ అవుతున్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ అవుతుంది."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"మీ వృథా సమయం <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>కి ముగిసే వరకు"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"మీ వృథా సమయం ముగిసేవరకు"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ఒక నిమిషం పాటు (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> వరకు)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d నిమిషాల పాటు (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> వరకు)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ఒక గంట పాటు (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> వరకు)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d గంటల పాటు (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> వరకు)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ఒక నిమిషానికి"</item>
- <item quantity="other" msgid="6924190729213550991">"%d నిమిషాలకి"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ఒక గంటకు"</item>
- <item quantity="other" msgid="5408537517529822157">"%d గంటలకు"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d నిమిషాల పాటు (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> వరకు)</item>
+ <item quantity="one">ఒక నిమిషం పాటు (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> వరకు)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d గంటల పాటు (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> వరకు)</item>
+ <item quantity="one">ఒక గంట పాటు (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> వరకు)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d నిమిషాల పాటు</item>
+ <item quantity="one">ఒక నిమిషం పాటు</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d గంటల పాటు</item>
+ <item quantity="one">ఒక గంట పాటు</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> వరకు"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"నిరవధికంగా"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"కుదించండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index bb972e4..230e915 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"ซิมการ์ดของคุณถูกล็อกด้วย PUK พิมพ์รหัส PUK เพื่อปลดล็อก"</string>
<string name="needPuk2" msgid="4526033371987193070">"พิมพ์ PUK2 เพื่อยกเลิกการปิดกั้นซิมการ์ด"</string>
<string name="enablePin" msgid="209412020907207950">"ไม่สำเร็จ เปิดใช้การล็อกซิม/RUIM"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่ซิมจะถูกล็อก"</item>
- <item quantity="other" msgid="7530597808358774740">"คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่ซิมจะถูกล็อก"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">คุณพยายามได้อีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้งก่อนที่ซิมจะล็อก</item>
+ <item quantity="one">คุณพยายามได้อีก <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งก่อนที่ซิมจะล็อก</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"หมายเลขผู้โทรเข้า"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 วินาทีที่แล้ว"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> วินาทีที่แล้ว"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 นาทีที่ผ่านมา"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> นาทีที่ผ่านมา"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ชั่วโมงที่ผ่านมา"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> ชั่วโมงที่ผ่านมา"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"> <xliff:g id="COUNT_1">%d</xliff:g> วันที่แล้ว</item>
+ <item quantity="one"> <xliff:g id="COUNT_0">%d</xliff:g> วันที่แล้ว</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"เดือนที่แล้ว"</string>
<string name="older" msgid="5211975022815554840">"เก่ากว่า"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"เมื่อวาน"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> วันที่ผ่านมา"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"ใน 1 วินาที"</item>
- <item quantity="other" msgid="1241926116443974687">"ใน <xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"ใน 1 นาที"</item>
- <item quantity="other" msgid="3330713936399448749">"ใน <xliff:g id="COUNT">%d</xliff:g> นาที"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"ใน 1 ชั่วโมง"</item>
- <item quantity="other" msgid="547290677353727389">"ใน <xliff:g id="COUNT">%d</xliff:g> ชั่วโมง"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"พรุ่งนี้"</item>
- <item quantity="other" msgid="5109449375100953247">"ใน <xliff:g id="COUNT">%d</xliff:g> วัน"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 วินาทีที่แล้ว"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> วินาทีที่ผ่านมา"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 นาทีที่ผ่านมา"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> นาทีที่ผ่านมา"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ชั่วโมงที่ผ่านมา"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> ชั่วโมงที่ผ่านมา"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"เมื่อวาน"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> วันที่ผ่านมา"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"ใน 1 วินาที"</item>
- <item quantity="other" msgid="5495880108825805108">"ใน <xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"ใน 1 นาที"</item>
- <item quantity="other" msgid="4216113292706568726">"ใน <xliff:g id="COUNT">%d</xliff:g> นาที"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ใน 1 ชั่วโมง"</item>
- <item quantity="other" msgid="3705373766798013406">"ใน <xliff:g id="COUNT">%d</xliff:g> ชั่วโมง"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"พรุ่งนี้"</item>
- <item quantity="other" msgid="2973062968038355991">"ใน <xliff:g id="COUNT">%d</xliff:g> วัน"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"ในวันที่ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"ที่ <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ใน <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"สัปดาห์"</string>
<string name="year" msgid="4001118221013892076">"ปี"</string>
<string name="years" msgid="6881577717993213522">" ปี"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 วินาที"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 นาที"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> นาที"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ชั่วโมง"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> ชั่วโมง"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> วินาที</item>
+ <item quantity="one">1 วินาที</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> นาที</item>
+ <item quantity="one">1 นาที</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> ชั่วโมง</item>
+ <item quantity="one">1 ชั่วโมง</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"ไม่มี"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"เสียงเรียกเข้า"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"ไม่ทราบเสียงเรียกเข้า"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"เครือข่าย WiFi ที่ใช้งานได้"</item>
- <item quantity="other" msgid="4192424489168397386">"เครือข่าย WiFi ใช้งานได้"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"เปิดเครือข่าย WiFi ที่ใช้งานได้"</item>
- <item quantity="other" msgid="7915895323644292768">"เปิดเครือข่าย WiFi ที่ใช้งานได้"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">มีหลายเครือข่าย Wi-Fi ที่ใช้งานได้</item>
+ <item quantity="one">มี 1 เครือข่าย Wi-Fi ที่ใช้งานได้</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">มีหลายเครือข่าย Wi-Fi สาธารณะที่ใช้งานได้</item>
+ <item quantity="one">มี 1 เครือข่าย Wi-Fi สาธารณะที่ใช้งานได้</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"ลงชื่อเข้าใช้เครือข่าย"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ตกลง"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"เชื่อมต่อเป็นอุปกรณ์สื่อ"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"เชื่อมต่อเป็นกล้องถ่ายรูป"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"เชื่อมต่อเป็นอุปกรณ์ MIDI แล้ว"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"เชื่อมต่อเป็นตัวติดตั้ง"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"เชื่อมต่อกับอุปกรณ์เสริม USB แล้ว"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"แตะสำหรับตัวเลือก USB อื่นๆ"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 รายการที่ตรงกัน"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> จาก <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> จาก <xliff:g id="TOTAL">%d</xliff:g> รายการ</item>
+ <item quantity="one">ตรงกัน 1 รายการ</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"เสร็จสิ้น"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"กำลังยกเลิกการต่อเชื่อมที่จัดเก็บข้อมูล USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"กำลังยกเลิกการต่อเชื่อมการ์ด SD..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN สั้นเกินไป ต้องมีอย่างน้อย 4 หลัก"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"ลองอีกใน 1 วิ"</item>
- <item quantity="other" msgid="4730868920742952817">"ลองอีกใน <xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">ลองอีกครั้งใน <xliff:g id="COUNT">%d</xliff:g> วินาที</item>
+ <item quantity="one">ลองอีกครั้งใน 1 วินาที</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"ลองอีกครั้งในภายหลัง"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"กวาดนิ้วบนลงล่างเพื่อออกจากโหมดเต็มหน้าจอ"</string>
<string name="done_label" msgid="2093726099505892398">"เสร็จสิ้น"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"เพื่อช่วยปรับปรุงอายุการใช้งานแบตเตอรี่ โหมดประหยัดแบตเตอรี่จะลดการทำงานของอุปกรณ์และจำกัดการสั่น บริการตำแหน่ง และข้อมูลแบ็กกราวด์ส่วนใหญ่ สำหรับอีเมล การรับส่งข้อความ และแอปอื่นๆ ที่ใช้การซิงค์จะไม่อัปเดตหากคุณไม่เปิดขึ้นมา\n\nโหมดประหยัดแบตเตอรี่จะปิดโดยอัตโนมัติขณะชาร์จอุปกรณ์"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"จนกว่าจะสิ้นสุดช่วงเวลาที่เครื่องไม่ทำงานในเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"จนกว่าจะสิ้นสุดช่วงเวลาเครื่องไม่ทำงาน"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1 นาที (จนถึงเวลา <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d นาที (จนถึงเวลา <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1 ชั่วโมง (จนถึงเวลา <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d ชั่วโมง (จนถึงเวลา <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 นาที"</item>
- <item quantity="other" msgid="6924190729213550991">"%d นาที"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 ชั่วโมง"</item>
- <item quantity="other" msgid="5408537517529822157">"%d ชั่วโมง"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">ระยะเวลา %1$d นาที (จนถึงเวลา <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">ระยะเวลา 1 นาที (จนถึงเวลา <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">ระยะเวลา %1$d ชั่วโมง (จนถึงเวลา <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">ระยะเวลา 1 ชั่วโมง (จนถึงเวลา <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">ระยะเวลา %d นาที</item>
+ <item quantity="one">ระยะเวลา 1 นาที</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">ระยะเวลา %d ชั่วโมง</item>
+ <item quantity="one">ระยะเวลา 1 ชั่วโมง</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"จนถึงเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"ไม่มีกำหนด"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"ยุบ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 97dda674..98eec08 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Na-PUK-lock ang iyong SIM card. I-type ang PUK code upang i-unlock ito."</string>
<string name="needPuk2" msgid="4526033371987193070">"I-type ang PUK2 upang i-unblock ang SIM card."</string>
<string name="enablePin" msgid="209412020907207950">"Hindi matagumpay, i-enable ang SIM/RUIM Lock."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok bago ma-lock ang SIM."</item>
- <item quantity="other" msgid="7530597808358774740">"Mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok bago ma-lock ang SIM."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> natitirang pagsubok bago ma-lock ang SIM.</item>
+ <item quantity="other">Mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> na natitirang pagsubok bago ma-lock ang SIM.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Papasok na Caller ID"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"Nais paganahin ng <xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ang Galugarin sa pamamagitan ng pagpindot. Kapag naka-on ang Galugarin sa pamamagitan ng pagpindot, maaari mong marinig o makita ang mga paglalarawan ng nasa ilalim ng iyong daliri o maaari kang magsagawa ng mga galaw upang makipag-ugnayan sa telepono."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 buwan ang nakalipas"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Bago ang nakalipas na 1 buwan"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 segundo ang nakakalipas"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> (na) segundo ang nakalipas"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 minuto ang nakalipas"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> (na) minuto ang nakalipas"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 oras ang nakalipas"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> (na) oras ang nakalipas"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Huling <xliff:g id="COUNT_1">%d</xliff:g> araw</item>
+ <item quantity="other">Huling <xliff:g id="COUNT_1">%d</xliff:g> na araw</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Nakaraang buwan"</string>
<string name="older" msgid="5211975022815554840">"Mas luma"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"kahapon"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> (na) araw ang nakalipas"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"sa 1 segundo"</item>
- <item quantity="other" msgid="1241926116443974687">"sa <xliff:g id="COUNT">%d</xliff:g> (na) segundo"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"sa 1 minuto"</item>
- <item quantity="other" msgid="3330713936399448749">"sa <xliff:g id="COUNT">%d</xliff:g> (na) minuto"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"sa 1 oras"</item>
- <item quantity="other" msgid="547290677353727389">"sa <xliff:g id="COUNT">%d</xliff:g> (na) oras"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"bukas"</item>
- <item quantity="other" msgid="5109449375100953247">"sa <xliff:g id="COUNT">%d</xliff:g> (na) araw"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 segundo ang nakalipas"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> (na) segundo ang nakalipas"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 minuto ang nakalipas"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> (na) minuto ang nakalipas"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 oras ang nakalipas"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> (na) oras ang nakalipas"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"kahapon"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> (na) araw ang nakalipas"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"sa 1 seg"</item>
- <item quantity="other" msgid="5495880108825805108">"sa <xliff:g id="COUNT">%d</xliff:g> (na) segundo"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"sa 1 min"</item>
- <item quantity="other" msgid="4216113292706568726">"sa <xliff:g id="COUNT">%d</xliff:g> (na) minuto"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"sa 1 oras"</item>
- <item quantity="other" msgid="3705373766798013406">"sa <xliff:g id="COUNT">%d</xliff:g> (na) oras"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"bukas"</item>
- <item quantity="other" msgid="2973062968038355991">"sa <xliff:g id="COUNT">%d</xliff:g> (na) araw"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"sa <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"nang <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"sa <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"mga linggo"</string>
<string name="year" msgid="4001118221013892076">"taon"</string>
<string name="years" msgid="6881577717993213522">"mga taon"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 segundo"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> (na) segundo"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 minuto"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> (na) minuto"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 oras"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> (na) oras"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> segundo</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na segundo</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> minuto</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na minuto</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> oras</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> na oras</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Problema sa video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Hindi wasto ang video na ito para sa streaming sa device na ito."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Hindi ma-play ang video na ito."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Wala"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Mga Ringtone"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Hindi kilalang ringtone"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Available ang Wi-Fi network"</item>
- <item quantity="other" msgid="4192424489168397386">"Available ang mga Wi-Fi network"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Available ang bukas na Wi-Fi network"</item>
- <item quantity="other" msgid="7915895323644292768">"Buksan ang mga available na Wi-Fi network"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Available ang mga Wi-Fi network</item>
+ <item quantity="other">Available ang mga Wi-Fi network</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Available ang mga bukas na Wi-Fi network</item>
+ <item quantity="other">Available ang mga bukas na Wi-Fi network</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Mag-sign in sa network ng Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Mag-sign in sa network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Nakakonekta bilang isang media device"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Nakakonekta bilang isang camera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Nakakonekta bilang isang MIDI device"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Nakakonekta bilang isang installer"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Nakakonekta sa isang accessory ng USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Pindutin para sa iba pang mga pagpipilian sa USB."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Laktawan"</string>
<string name="no_matches" msgid="8129421908915840737">"Walang mga tugma"</string>
<string name="find_on_page" msgid="1946799233822820384">"Maghanap sa pahina"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 tugma"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ng <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> ng <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> ng <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Tapos na"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Ina-unmount ang USB storage..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Ina-unmount ang SD card..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Gumawa ng PIN para sa pagbago sa mga paghihigpit"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Hindi nagtutugma ang mga PIN. Subukang muli."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Masyadong maikli ang PIN. Hindi dapat mas maikli sa 4 na digit."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Subukan muli sa 1 seg"</item>
- <item quantity="other" msgid="4730868920742952817">"Subukan muli sa <xliff:g id="COUNT">%d</xliff:g> seg"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Subukang muli sa loob ng <xliff:g id="COUNT">%d</xliff:g> segundo</item>
+ <item quantity="other">Subukang muli sa loob ng <xliff:g id="COUNT">%d</xliff:g> na segundo</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Subukang muli sa ibang pagkakataon"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Mag-swipe pababa mula sa itaas upang lumabas sa full screen."</string>
<string name="done_label" msgid="2093726099505892398">"Tapos na"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Upang matulungang pagbutihin ang tagal ng baterya, binabawasan ng pangtipid ng baterya ang pagganap ng iyong device at nililimitahan ang pag-vibrate, mga serbisyo ng lokasyon at karamihan sa data ng background. Maaaring hindi mag-update ang email, pagmemensahe at iba pang mga app na umaasa sa pagsi-sync maliban kung buksan mo ang mga iyon.\n\nAwtomatikong nag-o-off ang pangtipid ng baterya kapag nagcha-charge ang iyong device."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hanggang sa matapos ang iyong downtime nang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Hanggang magtapos ang iyong downtime"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Sa loob ng isang minuto (hanggang <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Sa loob ng %1$d (na) minuto (hanggang <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Sa loob ng isang oras (hanggang <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Sa loob ng %1$d (na) oras (hanggang <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item>
- <item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Sa loob ng isang oras"</item>
- <item quantity="other" msgid="5408537517529822157">"Sa loob ng %d (na) oras"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Sa loob ng %1$d minuto (hanggang <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Sa loob ng %1$d na minuto (hanggang <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Sa loob ng %1$d oras (hanggang <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Sa loob ng %1$d na oras (hanggang <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Sa loob ng %d minuto</item>
+ <item quantity="other">Sa loob ng %d na minuto</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Sa loob ng %d oras</item>
+ <item quantity="other">Sa loob ng %d na oras</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Walang tiyak na katapusan"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"I-collapse"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c0fd411..3489298 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM kartınızın PUK kilidi devrede. Kilidi açmak için PUK kodunu yazın."</string>
<string name="needPuk2" msgid="4526033371987193070">"Engellenen SIM kartı açmak için PUK2 kodunu yazın."</string>
<string name="enablePin" msgid="209412020907207950">"Başarısız. SIM/RUIM Kilidini etkinleştirin."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"SIM kilitlenmeden önce <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- <item quantity="other" msgid="7530597808358774740">"SIM kilitlenmeden önce <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">SIM kilitlenmeden önce <xliff:g id="NUMBER_1">%d</xliff:g> deneme hakkınız kaldı.</item>
+ <item quantity="one">SIM kilitlenmeden önce <xliff:g id="NUMBER_0">%d</xliff:g> deneme hakkınız kaldı.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Gelen Çağrı Kimliği"</string>
@@ -200,7 +200,7 @@
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
<string name="global_action_settings" msgid="1756531602592545966">"Ayarlar"</string>
- <string name="global_action_voice_assist" msgid="7751191495200504480">"Ses Yardımı"</string>
+ <string name="global_action_voice_assist" msgid="7751191495200504480">"Sesli Yardım"</string>
<string name="global_action_lockdown" msgid="8751542514724332873">"Şimdi kilitle"</string>
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
@@ -1004,7 +1004,7 @@
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Tablet kilidini <xliff:g id="NUMBER">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. Tablet şimdi fabrika varsayılanına sıfırlanacak."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"TV\'nizin kilidini <xliff:g id="NUMBER">%d</xliff:g> kez hatalı bir şekilde açmaya çalıştınız. TV\'niz şimdi fabrika ayarlarına sıfırlanacaktır."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Telefon kilidini <xliff:g id="NUMBER">%d</xliff:g> defa yanlış bir şekilde açmaya çalıştınız. Telefon şimdi fabrika varsayılanına sıfırlanacak."</string>
- <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> saniye içinde yeniden deneyin."</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Deseni unuttunuz mu?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Hesap kilidini açma"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Çok fazla sayıda desen denemesi yapıldı"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>, Dokunarak Keşfet özelliğini etkinleştirmek istiyor. Dokunarak Keşfet açık olduğunda parmağınızın altındaki öğelere ait açıklamaları duyabilir veya görebilir ya da telefonla etkileşimde bulunmak için birtakım hareketler yapabilirsiniz."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 ay önce"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 ay önce"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 saniye önce"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> saniye önce"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 dakika önce"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> dakika önce"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 saat önce"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> saat önce"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">Son <xliff:g id="COUNT_1">%d</xliff:g> gün</item>
+ <item quantity="one">Son <xliff:g id="COUNT_0">%d</xliff:g> gün</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Son ay"</string>
<string name="older" msgid="5211975022815554840">"Daha eski"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"dün"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> gün önce"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 saniye içinde"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> saniye içinde"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 dakika içinde"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> dakika içinde"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 saat içinde"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> saat içinde"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"yarın"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> gün içinde"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 saniye önce"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> saniye önce"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 dak. önce"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> dakika önce"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 saat önce"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> saat önce"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"dün"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> gün önce"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 san. içinde"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> saniye içinde"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 dak. içinde"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> dakika içinde"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 saat içinde"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> saat içinde"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"yarın"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> gün içinde"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> tarihinde"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> yılında"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"hafta"</string>
<string name="year" msgid="4001118221013892076">"yıl"</string>
<string name="years" msgid="6881577717993213522">"yıl"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 saniye"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> saniye"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 dakika"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> dakika"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 saat"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> saat"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> saniye</item>
+ <item quantity="one">1 saniye</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> dakika</item>
+ <item quantity="one">1 dakika</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> saat</item>
+ <item quantity="one">1 saat</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video sorunu"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Bu video bu cihazda akış için uygun değil."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Bu video oynatılamıyor."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Yok"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Zil sesleri"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Bilinmeyen zil sesi"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Kablosuz ağ var"</item>
- <item quantity="other" msgid="4192424489168397386">"Kablosuz ağlar var"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Kullanılabilir kablosuz ağı aç"</item>
- <item quantity="other" msgid="7915895323644292768">"Kullanılabilir kablosuz ağları aç"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Kablosuz ağlar var</item>
+ <item quantity="one">Kablosuz ağ var</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Kullanılabilir Kablosuz ağları aç</item>
+ <item quantity="one">Kullanılabilir Kablosuz ağı aç</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Kablosuz ağda oturum açın"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Ağda oturum açın"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Medya cihazı olarak bağlandı"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera olarak bağlandı"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI cihaz olarak bağlandı"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Yükleyici olarak bağlandı"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB aksesuarına bağlandı"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Diğer USB seçenekleri için dokunun."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Atla"</string>
<string name="no_matches" msgid="8129421908915840737">"Eşleşme yok"</string>
<string name="find_on_page" msgid="1946799233822820384">"Sayfada bul"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 eşleşme"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> / <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 eşleşme</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Bitti"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB belleğin bağlantısı kesiliyor…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD kartın bağlantısı kesiliyor…"</string>
@@ -1675,7 +1615,7 @@
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Yanlış Desen"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Yanlış Şifre"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"Yanlış PIN"</string>
- <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> saniye içinde yeniden deneyin."</string>
+ <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"Deseninizi çizin"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN kodunu girin"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"PIN\'i girin"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Kısıtlamaları değiştirmek için PIN oluşturun"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN\'ler eşleşmiyor. Tekrar deneyin."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN çok kısa. En az 4 basamaklı olmalı."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 saniye içinde tekrar deneyin"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> saniye içinde tekrar deneyin"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> saniye içinde tekrar deneyin</item>
+ <item quantity="one">1 saniye içinde tekrar deneyin</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Daha sonra tekrar deneyin"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Tam ekrandan çıkmak için yukarıdan aşağıya hızlıca kaydırın."</string>
<string name="done_label" msgid="2093726099505892398">"Bitti"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Pil tasarrufu özelliği, pil ömrünü iyileştirmeye yardımcı olmak için cihazın performansını düşürür, titreşimi, konum hizmetlerini ve arka plan verilerinin çoğunu sınırlar. Senkronizasyona dayalı olarak çalışan e-posta, mesajlaşma uygulamaları ve diğer uygulamalar, bunları açmadığınız sürece güncellenmeyebilir.\n\nCihazınız şarj olurken pil tasarrufu otomatik olarak kapatılır."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Bildirim istenmeyen zaman <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatinde sona erene kadar"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Bildirim istenmeyen zaman bitene kadar"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Bir dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Bir saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item>
- <item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Bir saat süreyle"</item>
- <item quantity="other" msgid="5408537517529822157">"%d saat süreyle"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Bir dakika için (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Bir saat için (şu saate kadar: <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d dakika süreyle</item>
+ <item quantity="one">Bir dakika süreyle</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d saat için</item>
+ <item quantity="one">Bir saat için</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Şu saate kadar: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Süresiz"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Daralt"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 664976a6..bb48a43 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -61,10 +61,12 @@
<string name="needPuk" msgid="919668385956251611">"SIM-карта заблок. PUK-кодом. Введіть PUK-код, щоб її розблок."</string>
<string name="needPuk2" msgid="4526033371987193070">"Введ. PUK2, щоб розбл. SIM-карту."</string>
<string name="enablePin" msgid="209412020907207950">"Помилка. Увімкніть блокування SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"У вас залишилась <xliff:g id="NUMBER">%d</xliff:g> спроба. Після цього SIM-карту буде заблоковано."</item>
- <item quantity="other" msgid="7530597808358774740">"У вас залишилося стільки спроб: <xliff:g id="NUMBER">%d</xliff:g>. Після цього SIM-карту буде заблоковано."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">У вас залишилась <xliff:g id="NUMBER_1">%d</xliff:g> спроба. Після цього SIM-карту буде заблоковано.</item>
+ <item quantity="few">У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде заблоковано.</item>
+ <item quantity="many">У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроб. Після цього SIM-карту буде заблоковано.</item>
+ <item quantity="other">У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде заблоковано.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Вхідн. ід. абонента"</string>
@@ -1131,73 +1133,14 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 сек. тому"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> сек. тому"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 хвилину тому"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> хв. тому"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 год. тому"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> год. тому"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Останній <xliff:g id="COUNT_1">%d</xliff:g> день</item>
+ <item quantity="few">Останні <xliff:g id="COUNT_1">%d</xliff:g> дні</item>
+ <item quantity="many">Останні <xliff:g id="COUNT_1">%d</xliff:g> днів</item>
+ <item quantity="other">Останні <xliff:g id="COUNT_1">%d</xliff:g> днів</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Останній міс."</string>
<string name="older" msgid="5211975022815554840">"Давніше"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"учора"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> дн. тому"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"через 1 сек."</item>
- <item quantity="other" msgid="1241926116443974687">"через <xliff:g id="COUNT">%d</xliff:g> сек."</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"через 1 хв."</item>
- <item quantity="other" msgid="3330713936399448749">"через <xliff:g id="COUNT">%d</xliff:g> хв."</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"через 1 год."</item>
- <item quantity="other" msgid="547290677353727389">"через <xliff:g id="COUNT">%d</xliff:g> год."</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"завтра"</item>
- <item quantity="other" msgid="5109449375100953247">"через <xliff:g id="COUNT">%d</xliff:g> дн."</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 сек. тому"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> сек. тому"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 хв. тому"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> хв. тому"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 годину тому"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> год. тому"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"учора"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> дн. тому"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"через 1 с."</item>
- <item quantity="other" msgid="5495880108825805108">"через <xliff:g id="COUNT">%d</xliff:g> сек."</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"через 1 хв."</item>
- <item quantity="other" msgid="4216113292706568726">"через <xliff:g id="COUNT">%d</xliff:g> хв."</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"через 1 год."</item>
- <item quantity="other" msgid="3705373766798013406">"через <xliff:g id="COUNT">%d</xliff:g> год."</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"завтра"</item>
- <item quantity="other" msgid="2973062968038355991">"через <xliff:g id="COUNT">%d</xliff:g> дн."</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"о <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"у <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1156,24 @@
<string name="weeks" msgid="6509623834583944518">"тижн."</string>
<string name="year" msgid="4001118221013892076">"рік"</string>
<string name="years" msgid="6881577717993213522">"р."</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 с"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> с"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 хв"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> хв"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 год"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> год"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> секунда</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> хвилина</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> хвилини</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> хвилин</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> хвилини</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> година</item>
+ <item quantity="few"><xliff:g id="COUNT">%d</xliff:g> години</item>
+ <item quantity="many"><xliff:g id="COUNT">%d</xliff:g> годин</item>
+ <item quantity="other"><xliff:g id="COUNT">%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>
@@ -1333,14 +1282,18 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Немає"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодії"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Невідома мелодія"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi мережа доступна"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi мережі доступні"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Відкрита Wi-Fi мережа доступна"</item>
- <item quantity="other" msgid="7915895323644292768">"Відкриті Wi-Fi мережі доступні"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Мережі Wi-Fi доступні</item>
+ <item quantity="few">Мережі Wi-Fi доступні</item>
+ <item quantity="many">Мережі Wi-Fi доступні</item>
+ <item quantity="other">Мережі Wi-Fi доступні</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Відкриті мережі Wi-Fi доступні</item>
+ <item quantity="few">Відкриті мережі Wi-Fi доступні</item>
+ <item quantity="many">Відкриті мережі Wi-Fi доступні</item>
+ <item quantity="other">Відкриті мережі Wi-Fi доступні</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Вхід у мережу Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Вхід у мережу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1369,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Під’єднано як носій"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Під’єднано як камеру"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Підключено як пристрій MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Під’єднано як програму встановлення"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Під’єднано до аксесуара USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Торкніться, щоб побачити інші параметри USB."</string>
@@ -1531,10 +1485,12 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 збіг"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> з <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> із <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="few"><xliff:g id="INDEX">%d</xliff:g> із <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> із <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> із <xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Відключення носія USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Відключення карти SD..."</string>
@@ -1820,10 +1776,12 @@
<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_too_short" msgid="8173982756265777792">"PIN-код закороткий. Має бути принаймні 4 цифри."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Повтор за 1 с"</item>
- <item quantity="other" msgid="4730868920742952817">"Повтор за <xliff:g id="COUNT">%d</xliff:g> с"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Повтор через <xliff:g id="COUNT">%d</xliff:g> секунду</item>
+ <item quantity="few">Повтор через <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ <item quantity="many">Повтор через <xliff:g id="COUNT">%d</xliff:g> секунд</item>
+ <item quantity="other">Повтор через <xliff:g id="COUNT">%d</xliff:g> секунди</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Спробуйте пізніше"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Проведіть пальцем зверху вниз, щоб вийти з повноекранного режиму."</string>
<string name="done_label" msgid="2093726099505892398">"Готово"</string>
@@ -1849,22 +1807,30 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Щоб подовжити час роботи акумулятора, функція заощадження заряду акумулятора знижує продуктивність пристрою, а також обмежує вібрацію, функції служб локації та передавання більшості фонових даних. Електронна пошта, чати й інші додатки, які синхронізуються, можуть не оновлюватися, доки ви їх не відкриєте.\n\nФункція заощадження заряду акумулятора автоматично вимикається під час заряджання пристрою."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Термін простою закінчується о <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"До завершення терміну простою"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Одну хвилину (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d хв (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Одну годину (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d год (до <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Протягом хвилини"</item>
- <item quantity="other" msgid="6924190729213550991">"Протягом %d хв"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Протягом години"</item>
- <item quantity="other" msgid="5408537517529822157">"Протягом %d год"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">%1$d хвилину (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d хвилини (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d хвилин (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d хвилини (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">%1$d годину (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="few">%1$d години (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="many">%1$d годин (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">%1$d години (до <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">%d хвилину</item>
+ <item quantity="few">%d хвилини</item>
+ <item quantity="many">%d хвилин</item>
+ <item quantity="other">%d хвилини</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">%d годину</item>
+ <item quantity="few">%d години</item>
+ <item quantity="many">%d годин</item>
+ <item quantity="other">%d години</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Без обмежень"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Згорнути"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 76cfe76..d107b09 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"آپ کا SIM کارڈ PUK مقفل ہے۔ PUK کوڈ کو غیر مقفل کرنے کیلئے اسے ٹائپ کریں۔"</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM کارڈ غیر مسدود کرنے کیلئے PUK2 ٹائپ کریں۔"</string>
<string name="enablePin" msgid="209412020907207950">"ناکام، SIM/RUIM لاک کو فعال کریں۔"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"SIM مقفل ہونے سے پہلے آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوشش بچی ہے۔"</item>
- <item quantity="other" msgid="7530597808358774740">"SIM مقفل ہونے سے پہلے آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوششیں بچی ہیں۔"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">آپ کے پاس <xliff:g id="NUMBER_1">%d</xliff:g> کوششیں بچی ہیں، اس کے بعد SIM مقفل ہو جائے گا۔</item>
+ <item quantity="one">آپ کے پاس <xliff:g id="NUMBER_0">%d</xliff:g> کوشش بچی ہے، اس کے بعد SIM مقفل ہو جائے گا۔</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"ان کمنگ کالر ID"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 سیکنڈ پہلے"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ پہلے"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 منٹ پہلے"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> منٹ پہلے"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 گھنٹہ پہلے"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے پہلے"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">گزشتہ <xliff:g id="COUNT_1">%d</xliff:g> دن</item>
+ <item quantity="one">گزشتہ <xliff:g id="COUNT_0">%d</xliff:g> دن</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"پچھلے مہینے"</string>
<string name="older" msgid="5211975022815554840">"پرانا"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"گزشتہ کل"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> دن پہلے"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 سیکنڈ میں"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ میں"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 منٹ میں"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> منٹ میں"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 گھنٹہ میں"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے میں"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"آنے والا کل"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> دن میں"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 سیکنڈ پہلے"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ پہلے"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 منٹ پہلے"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> منٹ پہلے"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 گھنٹہ پہلے"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے پہلے"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"گزشتہ کل"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> دن پہلے"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 سیکنڈ میں"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ میں"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 منٹ میں"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> منٹ میں"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 گھنٹہ میں"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے میں"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"آنے والا کل"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> دن میں"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> کو"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> میں"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"ہفتے"</string>
<string name="year" msgid="4001118221013892076">"سال"</string>
<string name="years" msgid="6881577717993213522">"سال"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 سیکنڈ"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 منٹ"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> منٹ"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 گھنٹہ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> گھنٹے"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> سیکنڈ</item>
+ <item quantity="one">1 سیکنڈ</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> منٹ</item>
+ <item quantity="one">1 منٹ</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> گھنٹے</item>
+ <item quantity="one">1 گھنٹہ</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"کوئی نہیں"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"رنگ ٹونز"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"نامعلوم رنگ ٹون"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi نیٹ ورک دستیاب ہے"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi نیٹ ورکس دستیاب ہیں"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"عوامی Wi-Fi نیٹ ورک دستیاب ہے"</item>
- <item quantity="other" msgid="7915895323644292768">"عوامی Wi-Fi نیٹ ورکس دستیاب ہیں"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi نیٹ ورکس دستیاب ہیں</item>
+ <item quantity="one">Wi-Fi نیٹ ورک دستیاب ہے</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">عوامی Wi-Fi نیٹ ورکس دستیاب ہیں</item>
+ <item quantity="one">عوامی Wi-Fi نیٹ ورک دستیاب ہے</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"نیٹ ورک میں سائن ان کریں"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"ٹھیک ہے"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"ایک میڈیا آلہ کے بطور مربوط کر دیا گیا"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"ایک کیمرہ کے بطور مربوط ہے"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"ایک MIDI آلہ کے بطور منسلک کیا گیا"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"ایک انسٹالر کے بطور مربوط ہے"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"ایک USB لوازم سے مربوط ہے"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"USB کے دوسرے اختیارات کیلئے چھوئیں۔"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 مماثلت"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 مماثلت</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"ہو گیا"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB اسٹوریج کو اَن ماؤںٹ کر رہا ہے…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD کارڈ کو اَن ماؤںٹ کر رہا ہے…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"تحدیدات میں ترمیم کرنے کیلئے ایک PIN بنائیں"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINs مماثل نہیں ہیں۔ دوبارہ کوشش کریں۔"</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN کافی چھوٹا ہے۔ کم از کم 4 ہندسے ہونا ضروری ہے۔"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 سیکنڈ میں دوبارہ کوشش کریں"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں</item>
+ <item quantity="one">1 سیکنڈ میں دوبارہ کوشش کریں</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"بعد میں دوبارہ کوشش کریں"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"مکمل اسکرین سے نکلنے کیلئے اوپر سے نیچے سوائپ کریں۔"</string>
<string name="done_label" msgid="2093726099505892398">"ہو گیا"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"بیٹری کی میعاد بہتر کرنے میں مدد کرنے کیلئے، بیٹری کی بچت آپ کے آلہ کی کارکردگی کم کر دیتی ہے اور وائبریشن، مقام کی سروسز اور پس منظر کا بیشتر ڈیٹا محدود کر دیتی ہے۔ ای میل، پیغام رسانی اور مطابقت پذیری پر مبنی دیگر ایپس ممکن ہے اس وقت تک اپ ڈیٹ نہ ہوں جب تک آپ انہیں نہ کھولیں۔\n\nآپ کا آلہ چارج ہوتے وقت بیٹری کی بچت خود بخود آف ہو جاتی ہے۔"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> پر آپ کا آخری وقت ختم ہونے تک"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"آپ کا ڈاؤن ٹائم ختم ہونے تک"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"ایک منٹ کیلئے (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> تک)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d منٹ کیلئے (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> تک)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"ایک گھنٹے کیلئے (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> تک)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d گھنٹوں کیلئے (<xliff:g id="FORMATTEDTIME">%2$s</xliff:g> تک)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"ایک منٹ کیلئے"</item>
- <item quantity="other" msgid="6924190729213550991">"%d منٹ کیلئے"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"ایک گھنٹے کیلئے"</item>
- <item quantity="other" msgid="5408537517529822157">"%d گھنٹوں کیلئے"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d منٹ کیلئے (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> تک)</item>
+ <item quantity="one">ایک منٹ کیلئے (تک <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d گھنٹے کیلئے (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> تک)</item>
+ <item quantity="one">ایک گھنٹہ کیلئے (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> تک)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d منٹ کیلئے</item>
+ <item quantity="one">ایک منٹ کیلئے</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d گھنٹے کیلئے</item>
+ <item quantity="one">ایک گھنٹہ کیلئے</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> تک"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"غیر متعینہ"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"سکیڑیں"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 30164e1..c69a4ee 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM kartangiz PUK kod bilan qulflangan. Uni qulfdan chiqarish uchun PUK kodni tering."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM kartani blokdan chiqarish uchun PUK2 raqamini kiriting."</string>
<string name="enablePin" msgid="209412020907207950">"Ishlamadi, SIM/RUIM qulfni yoqish."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"<xliff:g id="NUMBER">%d</xliff:g> marta uringaningizdan so‘ng, SIM karta qulflanib qoladi."</item>
- <item quantity="other" msgid="7530597808358774740">"<xliff:g id="NUMBER">%d</xliff:g> marta uringaningizdan so‘ng, SIM karta qulflanib qoladi."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Yana <xliff:g id="NUMBER_1">%d</xliff:g> ta muvaffaqiyatsiz urinishdan so‘ng SIM karta qulflanadi.</item>
+ <item quantity="one">Yana <xliff:g id="NUMBER_0">%d</xliff:g> ta muvaffaqiyatsiz urinishdan so‘ng SIM karta qulflanadi.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Kiruvchi raqami"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> teginib o‘rganish xususiyatini yoqishni xohlamoqda. Bu xususiyat yoqilganda, barmog‘ingiz ostidagi elementlar ta‘rifini ko‘rishingiz yoki eshitishingiz mumkin yoki telefon bilan o‘zaro bog‘lanish uchun barmog‘ingiz bilan imo-ishorali harakatlarni bajaring."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 oy oldin"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 oydan oldinroq"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 soniya oldin"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> soniya oldin"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 daqiqa oldin"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> daqiqa oldin"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 soat oldin"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> soat oldin"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">So‘nggi <xliff:g id="COUNT_1">%d</xliff:g> kun</item>
+ <item quantity="one">So‘nggi <xliff:g id="COUNT_0">%d</xliff:g> kun</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"O‘tgan oy"</string>
<string name="older" msgid="5211975022815554840">"Eskiroq"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"kecha"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> kun oldin"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 soniyada"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> soniyada"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 daqiqada"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> daqiqada"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 soatda"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> soatda"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ertaga"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> kunda"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 soniya oldin"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> soniya oldin"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 daq. oldin"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> daq. oldin"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 soat oldin"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> soat oldin"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"kecha"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> kun oldin"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 soniya da"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> soniya da"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 daq. da"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> daq. da"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 soatda"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> soatda"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ertaga"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> kunda"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g>da"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>da"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g>da"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"hafta"</string>
<string name="year" msgid="4001118221013892076">"yil"</string>
<string name="years" msgid="6881577717993213522">"yil"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 soniya"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> soniya"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 daqiqa"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> daqiqa"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 soat"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> soat"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniya</item>
+ <item quantity="one">1 soniya</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> daqiqa</item>
+ <item quantity="one">1 daqiqa</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soat</item>
+ <item quantity="one">1 soat</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Video muammosi"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Ushbu videoni mazkur qurilmada oqimli rejimda ijro etib bo‘lmaydi."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Ushbu videoni ijro etib bo‘lmadi."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Yo‘q"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Musiqalar"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Noma’lum musiqa"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Wi-Fi tarmoq mavjud"</item>
- <item quantity="other" msgid="4192424489168397386">"Wi-Fi tarmoqlar mavjud"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Mavjud Wi-Fi tarmoqni ochish"</item>
- <item quantity="other" msgid="7915895323644292768">"Mavjud Wi-Fi tarmoqlarini ochish"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Wi-Fi tarmoqlari mavjud emas</item>
+ <item quantity="one">Wi-Fi tarmog‘i mavjud emas</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Ochiq Wi-Fi tarmoqlari mavjud</item>
+ <item quantity="one">Ochiq Wi-Fi tarmog‘i mavjud</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Wi-Fi tarmoqqa kirish"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Tarmoqqa kiring"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Media qurilma sifatida ulangan"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera sifatida ulandi"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"MIDI qurilma sifatida ulandi"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"O‘rnatgich sifatida ulandi"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB jihozga ulangan"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Boshqa USB sozlamalarini ko‘rish uchun bosing."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Tashlab o‘tish"</string>
<string name="no_matches" msgid="8129421908915840737">"Topilmadi"</string>
<string name="find_on_page" msgid="1946799233822820384">"Sahifadan topish"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 mos topildi"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>dan <xliff:g id="INDEX">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 ta natija</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Tayyor"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"USB xotirasi uzilmoqda…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"SD xotira kartasi uzilmoqda…"</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Cheklovlarni o‘zgartirish uchun PIN kod yaratish"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN kodlar bir xil emas. Qaytadan urinib ko‘ring."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN kod juda qisqa. Kamida 4 raqamli bo‘lishi kerak."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 soniyadan keyin qayta urinib ko‘ring"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> soniyadan keyin qayta urinib ko‘ring"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring</item>
+ <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_mode_confirmation" msgid="7227416894979047467">"\"Butun ekran\" usulidan chiqish uchun barmoq bilan ekran tepasidan pastga tomon silang."</string>
<string name="done_label" msgid="2093726099505892398">"Tayyor"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash funksiyasi qurilmangiz unumdorligini kamaytiradi hamda uning tebranishi va orqa fonda internetdan foydalanishini cheklaydi. Sinxronlanishni talab qiladigan e-pochta, xabar almashinuv va boshqa ilovalar esa qachonki ularni ishga tushirganingizda yangilanadi.\n\nQurilma quvvat olayotganda quvvat tejash funksiyasi avtomatik tarzda o‘chadi."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Tanaffus vaqti tugaguncha – <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Nofoal vaqtingiz tugaguncha"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Bir daqiqa (ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d daqiqa (ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Bir soat (ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d soat (ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 daqiqa"</item>
- <item quantity="other" msgid="6924190729213550991">"%d daqiqa"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 soat"</item>
- <item quantity="other" msgid="5408537517529822157">"%d soat"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d daqiqa (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> gacha)</item>
+ <item quantity="one">Bir daqiqa (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> gacha)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d soat (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> gacha)</item>
+ <item quantity="one">Bir soat (<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g> gacha)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d daqiqa</item>
+ <item quantity="one">Bir daqiqa</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d soat</item>
+ <item quantity="one">Bir soat</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Uzluksiz ravishda"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Yig‘ish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 2bf3819..c19278e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khóa PUK. Nhập mã PUK để mở khóa thẻ SIM đó."</string>
<string name="needPuk2" msgid="4526033371987193070">"Nhập mã PUK2 để bỏ chặn thẻ SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Không thành công, kích hoạt tính năng khóa SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử trước khi SIM bị khóa."</item>
- <item quantity="other" msgid="7530597808358774740">"Bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử trước khi SIM bị khóa."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">Bạn còn <xliff:g id="NUMBER_1">%d</xliff:g> lần thử trước khi SIM bị khóa.</item>
+ <item quantity="one">Bạn còn <xliff:g id="NUMBER_0">%d</xliff:g> lần thử trước khi SIM bị khóa.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Số gọi đến"</string>
@@ -838,7 +838,7 @@
<string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Ngăn sử dụng một số tính năng trong chế độ bảo vệ phím."</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Nhà riêng"</item>
- <item msgid="869923650527136615">"ĐT di động"</item>
+ <item msgid="869923650527136615">"Di Động"</item>
<item msgid="7897544654242874543">"Cơ quan"</item>
<item msgid="1103601433382158155">"Số fax Cơ quan"</item>
<item msgid="1735177144948329370">"Số fax Nhà riêng"</item>
@@ -881,7 +881,7 @@
</string-array>
<string name="phoneTypeCustom" msgid="1644738059053355820">"Tùy chỉnh"</string>
<string name="phoneTypeHome" msgid="2570923463033985887">"Nhà riêng"</string>
- <string name="phoneTypeMobile" msgid="6501463557754751037">"ĐT di động"</string>
+ <string name="phoneTypeMobile" msgid="6501463557754751037">"Di Động"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"Cơ quan"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Số fax Cơ quan"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Số fax Nhà riêng"</string>
@@ -908,7 +908,7 @@
<string name="emailTypeHome" msgid="449227236140433919">"Nhà riêng"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Cơ quan"</string>
<string name="emailTypeOther" msgid="2923008695272639549">"Khác"</string>
- <string name="emailTypeMobile" msgid="119919005321166205">"ĐT di động"</string>
+ <string name="emailTypeMobile" msgid="119919005321166205">"Di Động"</string>
<string name="postalTypeCustom" msgid="8903206903060479902">"Tùy chỉnh"</string>
<string name="postalTypeHome" msgid="8165756977184483097">"Nhà riêng"</string>
<string name="postalTypeWork" msgid="5268172772387694495">"Cơ quan"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> muốn bật Khám phá bằng cách chạm. Khi Khám phá bằng cách chạm được bật, bạn có thể nghe hoặc xem mô tả dưới ngón tay bạn hoặc thực hiện cử chỉ để tương tác với điện thoại."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 tháng trước"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Trước 1 tháng trước"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 giây trước"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> giây trước"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 phút trước"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> phút trước"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 giờ trước"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> giờ trước"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ngày qua</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ngày qua</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Tháng trước"</string>
<string name="older" msgid="5211975022815554840">"Cũ hơn"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"hôm qua"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> ngày trước"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"trong 1 giây"</item>
- <item quantity="other" msgid="1241926116443974687">"trong <xliff:g id="COUNT">%d</xliff:g> giây"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"trong 1 phút"</item>
- <item quantity="other" msgid="3330713936399448749">"trong <xliff:g id="COUNT">%d</xliff:g> phút"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"trong 1 giờ"</item>
- <item quantity="other" msgid="547290677353727389">"trong <xliff:g id="COUNT">%d</xliff:g> giờ"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"ngày mai"</item>
- <item quantity="other" msgid="5109449375100953247">"trong <xliff:g id="COUNT">%d</xliff:g> ngày"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 giây trước"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> giây trước"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 phút trước"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> phút trước"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 giờ trước"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> giờ trước"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"hôm qua"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> ngày trước"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"trong 1 giây"</item>
- <item quantity="other" msgid="5495880108825805108">"trong <xliff:g id="COUNT">%d</xliff:g> giây"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"trong 1 phút"</item>
- <item quantity="other" msgid="4216113292706568726">"trong <xliff:g id="COUNT">%d</xliff:g> phút"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"trong 1 giờ"</item>
- <item quantity="other" msgid="3705373766798013406">"trong <xliff:g id="COUNT">%d</xliff:g> giờ"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"ngày mai"</item>
- <item quantity="other" msgid="2973062968038355991">"trong <xliff:g id="COUNT">%d</xliff:g> ngày"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"vào <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"trong <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"tuần"</string>
<string name="year" msgid="4001118221013892076">"năm"</string>
<string name="years" msgid="6881577717993213522">"năm"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 giây"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> giây"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 phút"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> phút"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 giờ"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> giờ"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> giây</item>
+ <item quantity="one">1 giây</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> phút</item>
+ <item quantity="one">1 phút</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> giờ</item>
+ <item quantity="one">1 giờ</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Sự cố video"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Video này không hợp lệ để phát trực tuyến đến thiết bị này."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Không thể phát video này."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Không"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Nhạc chuông"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Nhạc chuông không xác định"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Mạng Wi-Fi khả dụng"</item>
- <item quantity="other" msgid="4192424489168397386">"Mạng Wi-Fi khả dụng"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Mở mạng Wi-Fi khả dụng"</item>
- <item quantity="other" msgid="7915895323644292768">"Mở mạng Wi-Fi khả dụng"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">Các mạng Wi-Fi khả dụng</item>
+ <item quantity="one">Mạng Wi-Fi khả dụng</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">Mở các mạng Wi-Fi khả dụng</item>
+ <item quantity="one">Mở mạng Wi-Fi khả dụng</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Đăng nhập vào mạng Wi-Fi"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Đăng nhập vào mạng"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Được kết nối là thiết bị truyền thông"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Được kết nối là máy ảnh"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Đã kết nối dưới dạng thiết bị MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Được kết nối như trình cài đặt"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Đã kết nối với phụ kiện USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Chạm để có các tùy chọn USB khác."</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Bỏ qua"</string>
<string name="no_matches" msgid="8129421908915840737">"Không có kết quả nào phù hợp"</string>
<string name="find_on_page" msgid="1946799233822820384">"Tìm kiếm trên trang"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 kết quả phù hợp"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> trong tổng số <xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> trong số <xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="one">1 trận đấu</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Xong"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Đang ngắt kết nối bộ lưu trữ USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Đang ngắt kết nối thẻ SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Tạo mã PIN để hạn chế sửa đổi"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Mã PIN không khớp. Hãy thử lại."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Mã PIN quá ngắn. Phải có ít nhất 4 chữ số."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Hãy thử lại sau 1 giây"</item>
- <item quantity="other" msgid="4730868920742952817">"Hãy thử lại sau <xliff:g id="COUNT">%d</xliff:g> giây"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">Hãy thử lại sau <xliff:g id="COUNT">%d</xliff:g> giây</item>
+ <item quantity="one">Hãy thử lại sau 1 giây</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Hãy thử lại sau"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Vuốt từ trên xuống để thoát toàn màn hình."</string>
<string name="done_label" msgid="2093726099505892398">"Xong"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất thiết bị của bạn và hạn chế rung, dịch vụ vị trí và hầu hết dữ liệu nền. Email, nhắn tin và các ứng dụng khác dựa trên đồng bộ hóa có thể không cập nhật nếu bạn không mở chúng.\n\nTrình tiết kiệm pin tự động tắt khi thiết bị của bạn đang sạc."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Cho tới khi thời gian ngừng hoạt động của bạn kết thúc vào <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Cho đến khi thời gian ngừng hoạt động kết thúc"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Trong một phút (cho đến <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Trong %1$d phút (cho đến <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Trong một giờ (cho đến <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Trong %1$d giờ (cho đến <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Trong một phút"</item>
- <item quantity="other" msgid="6924190729213550991">"Trong %d phút"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Trong một giờ"</item>
- <item quantity="other" msgid="5408537517529822157">"Trong %d giờ"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">Trong %1$d phút (cho đến <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Trong một phút (cho đến <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">Trong %1$d giờ (cho đến <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">Trong một giờ (cho đến <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">Trong %d phút</item>
+ <item quantity="one">Trong một phút</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">Trong %d giờ</item>
+ <item quantity="one">Trong một giờ</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Cho đến <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Không giới hạn"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Thu gọn"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 307a1ea..745aa73 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -43,4 +43,12 @@
<!-- Flags enabling default window features. See Window.java -->
<bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
<bool name="config_defaultWindowFeatureContextMenu">false</bool>
+
+ <!-- Time adjustment, in milliseconds, applied to the default double tap threshold
+ used for gesture detection by the screen magnifier. -->
+ <integer name="config_screen_magnification_multi_tap_adjustment">25</integer>
+
+ <!-- Scale factor threshold used by the screen magnifier to determine when to switch from
+ panning to scaling the magnification viewport. -->
+ <item name="config_screen_magnification_scaling_threshold" format="float" type="dimen">0.1</item>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e280503..c76ff7f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"已对SIM卡进行PUK码锁定。请输入PUK码将其解锁。"</string>
<string name="needPuk2" msgid="4526033371987193070">"输入PUK2码以解锁SIM卡。"</string>
<string name="enablePin" msgid="209412020907207950">"失败,请开启SIM/RUIM卡锁定设置。"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。如果仍然失败,SIM卡将被锁定。"</item>
- <item quantity="other" msgid="7530597808358774740">"您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。如果仍然失败,SIM卡将被锁定。"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">您还可尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍不正确,SIM 卡将被锁定。</item>
+ <item quantity="one">您还可尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,SIM 卡将被锁定。</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"来电显示"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1秒前"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1分钟前"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g>分钟前"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1小时前"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g>小时前"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">过去 <xliff:g id="COUNT_1">%d</xliff:g> 天</item>
+ <item quantity="one">过去 <xliff:g id="COUNT_0">%d</xliff:g> 天</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"上个月"</string>
<string name="older" msgid="5211975022815554840">"往前"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"昨天"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g>天前"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1秒后"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g>秒后"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1分钟后"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g>分钟后"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1小时后"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g>小时后"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"明天"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> 天后"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1秒前"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g>秒前"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1分钟前"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g>分钟前"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1小时前"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g>小时前"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"昨天"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g>天前"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1秒后"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g>秒后"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1分钟后"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g>分钟后"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1小时后"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g>小时后"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"明天"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> 天后"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"日期:<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"年份:<xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"周"</string>
<string name="year" msgid="4001118221013892076">"年"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1秒"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g>秒"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1分钟"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g>分钟"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1小时"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g>小时"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒</item>
+ <item quantity="one">1 秒</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 分钟</item>
+ <item quantity="one">1 分钟</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 小时</item>
+ <item quantity="one">1 小时</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"无"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"未知铃声"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"有可用的WLAN网络"</item>
- <item quantity="other" msgid="4192424489168397386">"有可用的WLAN网络"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"打开可用的WLAN网络"</item>
- <item quantity="other" msgid="7915895323644292768">"打开可用的WLAN网络"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">有可用的 WLAN 网络</item>
+ <item quantity="one">有可用的 WLAN 网络</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">有可用的开放 WLAN 网络</item>
+ <item quantity="one">有可用的开放 WLAN 网络</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"登录到WLAN网络"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"登录网络"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"已作为媒体设备连接"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"作为相机连接"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"已作为 MIDI 设备连接"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"作为安装程序连接"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"已连接到USB配件"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"触摸可显示其他USB选项。"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 个匹配项"</item>
- <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 项,共 <xliff:g id="TOTAL">%d</xliff:g> 项"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other">第 <xliff:g id="INDEX">%d</xliff:g> 条结果(共 <xliff:g id="TOTAL">%d</xliff:g> 条)</item>
+ <item quantity="one">1 条结果</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"完成"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"正在卸载USB存储设备..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"正在卸载SD卡..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN码太短,至少应包含4位数字。"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1秒后重试"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g>秒后重试"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒后重试</item>
+ <item quantity="one">1 秒后重试</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"稍后重试"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"从顶部向下滑动即可退出全屏模式。"</string>
<string name="done_label" msgid="2093726099505892398">"完成"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到休息时间结束(<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"到休息时间结束"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1 分钟(到<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d 分钟(到<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1 小时(到<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d 小时(到<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1分钟"</item>
- <item quantity="other" msgid="6924190729213550991">"%d分钟"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1小时"</item>
- <item quantity="other" msgid="5408537517529822157">"%d小时"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">%1$d 分钟(到<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 分钟(到<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">%1$d 小时(到<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">1 小时(到<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">%d 分钟</item>
+ <item quantity="one">1 分钟</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">%d 小时</item>
+ <item quantity="one">1 小时</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"无限期"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"收起"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 83ae8f3..453043a 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"您的 SIM 卡已鎖定 PUK,請輸入 PUK 碼以解除鎖定。"</string>
<string name="needPuk2" msgid="4526033371987193070">"輸入 PUK2 為 SIM 卡解除封鎖。"</string>
<string name="enablePin" msgid="209412020907207950">"操作失敗,請啟用「SIM/RUIM 鎖定」。"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 將會被鎖定。"</item>
- <item quantity="other" msgid="7530597808358774740">"您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 將會被鎖定。"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 卡將會被鎖定。</item>
+ <item quantity="one">您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 卡將會被鎖定。</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"來電顯示"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 秒前"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 分鐘前"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘前"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 小時前"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">最近 <xliff:g id="COUNT_1">%d</xliff:g> 天</item>
+ <item quantity="one">最後 <xliff:g id="COUNT_0">%d</xliff:g> 天</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"上個月"</string>
<string name="older" msgid="5211975022815554840">"較舊"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"昨天"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 秒後"</item>
- <item quantity="other" msgid="1241926116443974687">"<xliff:g id="COUNT">%d</xliff:g> 秒後"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 分鐘後"</item>
- <item quantity="other" msgid="3330713936399448749">"<xliff:g id="COUNT">%d</xliff:g> 分鐘後"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 小時後"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> 小時後"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"明天"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> 天後"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 秒前"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 分鐘前"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> 分鐘前"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 小時前"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"昨天"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 秒後"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> 秒後"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 分鐘後"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> 分鐘後"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 小時後"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> 小時後"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"明天"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> 天後"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"於 <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"在 <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"於 <xliff:g id="YEAR">%s</xliff:g> 年"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"星期"</string>
<string name="year" msgid="4001118221013892076">"YEAR"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 分鐘"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分鐘"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 小時"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小時"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒</item>
+ <item quantity="one">1 秒</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 分鐘</item>
+ <item quantity="one">1 分鐘</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 小時</item>
+ <item quantity="one">1 小時</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"不明鈴聲"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"有 Wi-Fi 網絡可以連接"</item>
- <item quantity="other" msgid="4192424489168397386">"有 Wi-Fi 網絡可以連接"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"有公開的 Wi-Fi 網絡可以連接"</item>
- <item quantity="other" msgid="7915895323644292768">"有公開的 Wi-Fi 網絡可以連接"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">有可用的 Wi-Fi 網絡</item>
+ <item quantity="one">有可用的 Wi-Fi 網絡</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">有可用的公開 Wi-Fi 網絡</item>
+ <item quantity="one">有可用的公開 Wi-Fi 網絡</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"登入 Wi-Fi 網絡"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"登入網絡"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"已作為媒體裝置連線"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"已作為相機連線"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"已連接為 MIDI 裝置"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"已作為安裝程式連線"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"已連接到一個 USB 配件"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"輕觸即可顯示其他 USB 選項。"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 個相符項目"</item>
- <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 個,共 <xliff:g id="TOTAL">%d</xliff:g> 個"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> 個相符項目的第 <xliff:g id="INDEX">%d</xliff:g> 個</item>
+ <item quantity="one">1 個相符項目</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"完成"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"正在卸載 USB 儲存裝置..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"正在卸載 SD 記憶卡..."</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN 碼太短,至少必須為 4 位數。"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 秒後再試一次"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> 秒後再試一次"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒後再試一次</item>
+ <item quantity="one">1 秒後再試一次</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"稍後再試"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"由頂端往下快速滑動即可離開全螢幕。"</string>
<string name="done_label" msgid="2093726099505892398">"完成"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"節約電池用量模式有助於延長電池壽命,但這會降低裝置效能,並限制震動、定位服務及大部分背景數據傳輸。除非您啟用,否則電郵、短訊及其他需要使用同步功能的應用程式均不會更新。\n\n當裝置充電時,節約電池用量模式會自動關閉。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到停機時間於 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 結束"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"直到停機時間完結"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"需時 1 分鐘 (完成時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"需時 %1$d 分鐘 (完成時間 <xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"需時 1 小時 (完成時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"需時 %1$d 小時 (完成時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
- <item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 小時"</item>
- <item quantity="other" msgid="5408537517529822157">"%d 小時"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">需時 %1$d 分鐘 (完成時間:<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">需時 1 分鐘 (完成時間:<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">需時 %1$d 小時 (完成時間:<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">需時 1 小時 (完成時間:<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">需時 %d 分鐘</item>
+ <item quantity="one">需時 1 分鐘</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">需時 %d 小時</item>
+ <item quantity="one">需時 1 小時</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"完成時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"收合"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index c9e5364..b551b5f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"SIM 卡的 PUK 已鎖定。請輸入 PUK 碼解除鎖定。"</string>
<string name="needPuk2" msgid="4526033371987193070">"請輸入 PUK2 以解鎖 SIM 卡。"</string>
<string name="enablePin" msgid="209412020907207950">"操作失敗,請啟用 SIM/RUIM 鎖定。"</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。如果仍然失敗,SIM 卡將被鎖住。"</item>
- <item quantity="other" msgid="7530597808358774740">"您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。如果仍然失敗,SIM 卡將被鎖住。"</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="other">您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍然失敗,SIM 卡將被鎖定。</item>
+ <item quantity="one">您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,SIM 卡將被鎖定。</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"來電顯示"</string>
@@ -1131,73 +1131,12 @@
<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>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 秒以前"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> 秒前"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 分鐘以前"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> 分鐘前"</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 小時以前"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="other">過去 <xliff:g id="COUNT_1">%d</xliff:g> 天內</item>
+ <item quantity="one">過去 <xliff:g id="COUNT_0">%d</xliff:g> 天內</item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"上個月"</string>
<string name="older" msgid="5211975022815554840">"較舊"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"昨天"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"1 秒內"</item>
- <item quantity="other" msgid="1241926116443974687">"在 <xliff:g id="COUNT">%d</xliff:g> 秒內"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"1 分鐘內"</item>
- <item quantity="other" msgid="3330713936399448749">"在 <xliff:g id="COUNT">%d</xliff:g> 分鐘內"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"1 小時內"</item>
- <item quantity="other" msgid="547290677353727389">"<xliff:g id="COUNT">%d</xliff:g> 小時內"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"明天"</item>
- <item quantity="other" msgid="5109449375100953247">"<xliff:g id="COUNT">%d</xliff:g> 天內"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 秒以前"</item>
- <item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> 秒以前"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 分鐘以前"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> 分鐘以前"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 小時以前"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> 小時前"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"昨天"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> 天前"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"1 秒內"</item>
- <item quantity="other" msgid="5495880108825805108">"<xliff:g id="COUNT">%d</xliff:g> 秒內"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"1 分鐘內"</item>
- <item quantity="other" msgid="4216113292706568726">"<xliff:g id="COUNT">%d</xliff:g> 分鐘內"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"1 小時內"</item>
- <item quantity="other" msgid="3705373766798013406">"<xliff:g id="COUNT">%d</xliff:g> 小時內"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"明天"</item>
- <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> 天內"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"於 <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"於<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"於 <xliff:g id="YEAR">%s</xliff:g> 年"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"週"</string>
<string name="year" msgid="4001118221013892076">"年"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 秒"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> 秒"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 分鐘"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> 分鐘"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 小時"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> 小時"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 秒</item>
+ <item quantity="one">1 秒</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 分鐘</item>
+ <item quantity="one">1 分鐘</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> 小時</item>
+ <item quantity="one">1 小時</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>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"未知的鈴聲"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"已偵測到 Wi-Fi 網路"</item>
- <item quantity="other" msgid="4192424489168397386">"已偵測到 Wi-Fi 網路"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"開啟可用 Wi-Fi 網路"</item>
- <item quantity="other" msgid="7915895323644292768">"開啟可用 Wi-Fi 網路"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="other">有多個可用的 Wi-Fi 網路</item>
+ <item quantity="one">有一個可用的 Wi-Fi 網路</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="other">有多個可用的開放 Wi-Fi 網路</item>
+ <item quantity="one">有多個可用的開放 Wi-Fi 網路</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"登入 Wi-Fi 網路"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"登入網路"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"已視為媒體裝置連線"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"已視為相機連線"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"已採用 MIDI 模式連接到電腦"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"已視為安裝程式連線"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"已連接 USB 配件"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"輕觸即可顯示其他 USB 選項。"</string>
@@ -1531,10 +1471,10 @@
<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">
- <item quantity="one" msgid="8167147081136579439">"1 個相符項目"</item>
- <item quantity="other" msgid="4641872797067609177">"第 <xliff:g id="INDEX">%d</xliff:g> 個相符項目 (共 <xliff:g id="TOTAL">%d</xliff:g> 個相符項目)"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="other">第 <xliff:g id="INDEX">%d</xliff:g> 個相符項目 (共 <xliff:g id="TOTAL">%d</xliff:g> 個)</item>
+ <item quantity="one">1 個相符項目</item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"完成"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"正在卸載 USB 儲存裝置…"</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"正在卸載 SD 卡…"</string>
@@ -1820,10 +1760,10 @@
<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_too_short" msgid="8173982756265777792">"PIN 長度太短,至少必須為 4 位數。"</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"1 秒後再試一次"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> 秒後再試一次"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="other">請於 <xliff:g id="COUNT">%d</xliff:g> 秒後再試一次</item>
+ <item quantity="one">請於 1 秒後再試一次</item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"稍後再試"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"從頂端往下滑動即可退出全螢幕模式。"</string>
<string name="done_label" msgid="2093726099505892398">"完成"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"節約耗電量模式會透過降低裝置效能、震動限制、定位服務限制和大多數背景資料運作限制等方式,延長電池續航力。此外,如果未開啟電子郵件、簡訊和其他需要使用同步功能的應用程式,系統將不會自動更新這些應用程式。\n\n當您為裝置充電時,節約耗電量模式會自動關閉。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 停機時間結束"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"直到停機時間結束"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"1 分鐘 (結束時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"%1$d 分鐘 (結束時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"1 小時 (結束時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"%1$d 小時 (結束時間:<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
- <item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"1 小時"</item>
- <item quantity="other" msgid="5408537517529822157">"%d 小時"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="other">持續 %1$d 分鐘 (結束時間:<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">持續 1 分鐘 (結束時間:<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="other">持續 %1$d 小時 (結束時間:<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="one">持續 1 小時 (結束時間:<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="other">持續 %d 分鐘</item>
+ <item quantity="one">持續 1 分鐘</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="other">持續 %d 小時</item>
+ <item quantity="one">持續 1 小時</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"結束時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"收合"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 77cfdde..ea19554 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -61,10 +61,10 @@
<string name="needPuk" msgid="919668385956251611">"Ikhadi lakho le-SIM livalwe nge-PUK. Thayipha ikhodi ye-PUK ukulivula."</string>
<string name="needPuk2" msgid="4526033371987193070">"Thayipha i-PUK2 ukuze uvule ikhadi le-SIM."</string>
<string name="enablePin" msgid="209412020907207950">"Akuphumelelanga, nika amandla ukhiye we-SIM/RUIM."</string>
- <plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"Unemizamo engu-<xliff:g id="NUMBER">%d</xliff:g> ngaphambi kokuba i-SIM ikhiywe."</item>
- <item quantity="other" msgid="7530597808358774740">"Unemizamo engu-<xliff:g id="NUMBER">%d</xliff:g> ngaphambi kokuba i-SIM ikhiywe."</item>
- </plurals>
+ <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+ <item quantity="one">Unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ikhiywe.</item>
+ <item quantity="other">Unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ikhiywe.</item>
+ </plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
<string name="ClipMmi" msgid="6952821216480289285">"I-ID Yocingo Olungenayo"</string>
@@ -1131,73 +1131,12 @@
<string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"I-<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ifuna ukunika amandla i-Explore by Touch. Uma i-Explore by Touch ikhanya, ungezwa noma ubone izincazelo ezingaphansi komunwe wakho noma wenze izenzo zomzimba ukuze uxhumane nefoni."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"inyanga engu-1 edlule"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Ngaphambi kwenyanga engu-1 edlule"</string>
- <plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"1 isekhondi eledlule"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> amasekhondi adlule"</item>
- </plurals>
- <plurals name="num_minutes_ago">
- <item quantity="one" msgid="3306787433088810191">"1 iminithi elidlule"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> amaminithi adlule.."</item>
- </plurals>
- <plurals name="num_hours_ago">
- <item quantity="one" msgid="9150797944610821849">"1 ihora eledlule"</item>
- <item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> amahora adlule"</item>
- </plurals>
- <!-- no translation found for last_num_days:one (7555846096746489821) -->
+ <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+ <item quantity="one">Izinsuku zokugcina ezingu-<xliff:g id="COUNT_1">%d</xliff:g></item>
+ <item quantity="other">Izinsuku zokugcina ezingu-<xliff:g id="COUNT_1">%d</xliff:g></item>
+ </plurals>
<string name="last_month" msgid="3959346739979055432">"Inyanga edlule"</string>
<string name="older" msgid="5211975022815554840">"Okudala kakhulu"</string>
- <plurals name="num_days_ago">
- <item quantity="one" msgid="861358534398115820">"Izolo"</item>
- <item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> izinsuku ezedlule"</item>
- </plurals>
- <plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"esekhondini elingu-1"</item>
- <item quantity="other" msgid="1241926116443974687">"emasekhondini angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_minutes">
- <item quantity="one" msgid="8793095251325200395">"eminithini engu-1"</item>
- <item quantity="other" msgid="3330713936399448749">"emaminithini angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_hours">
- <item quantity="one" msgid="7164353342477769999">"ehoreni elingu-1"</item>
- <item quantity="other" msgid="547290677353727389">"emahoreni angu- <xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="in_num_days">
- <item quantity="one" msgid="5413088743009839518">"Kusasa"</item>
- <item quantity="other" msgid="5109449375100953247">"ezinsukwini ezingu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 isekhondi edlule"</item>
- <item quantity="other" msgid="3699169366650930415">"amasekhondi angu-<xliff:g id="COUNT">%d</xliff:g> edlule"</item>
- </plurals>
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one" msgid="6361490147113871545">"1 iminithi eledlule"</item>
- <item quantity="other" msgid="851164968597150710">"<xliff:g id="COUNT">%d</xliff:g> amaminithi adlule"</item>
- </plurals>
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one" msgid="4796212039724722116">"1 ihora eledlule"</item>
- <item quantity="other" msgid="6889970745748538901">"<xliff:g id="COUNT">%d</xliff:g> amahora adlule"</item>
- </plurals>
- <plurals name="abbrev_num_days_ago">
- <item quantity="one" msgid="8463161711492680309">"Izolo"</item>
- <item quantity="other" msgid="3453342639616481191">"<xliff:g id="COUNT">%d</xliff:g> izinsuku ezedlule"</item>
- </plurals>
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"esekhondini elingu-1"</item>
- <item quantity="other" msgid="5495880108825805108">"emasekhondini angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one" msgid="562786149928284878">"eminithini engu-1"</item>
- <item quantity="other" msgid="4216113292706568726">"emaminithini angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_hours">
- <item quantity="one" msgid="3274708118124045246">"ehoreni elingu-1"</item>
- <item quantity="other" msgid="3705373766798013406">"emahoreni angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
- <plurals name="abbrev_in_num_days">
- <item quantity="one" msgid="2178576254385739855">"Kusasa"</item>
- <item quantity="other" msgid="2973062968038355991">"ezinsukwini ezing-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"ngo-<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"e-<xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"phakathi- <xliff:g id="YEAR">%s</xliff:g>"</string>
@@ -1213,18 +1152,18 @@
<string name="weeks" msgid="6509623834583944518">"amaviki"</string>
<string name="year" msgid="4001118221013892076">"unyaka"</string>
<string name="years" msgid="6881577717993213522">"iminyaka"</string>
- <plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 isekhondi"</item>
- <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> amasekhondi"</item>
- </plurals>
- <plurals name="duration_minutes">
- <item quantity="one" msgid="4915414002546085617">"1 iminithi"</item>
- <item quantity="other" msgid="3165187169224908775">"<xliff:g id="COUNT">%d</xliff:g> amaminithi"</item>
- </plurals>
- <plurals name="duration_hours">
- <item quantity="one" msgid="8917467491248809972">"1 ihora"</item>
- <item quantity="other" msgid="3863962854246773930">"<xliff:g id="COUNT">%d</xliff:g> amahora"</item>
- </plurals>
+ <plurals name="duration_seconds" formatted="false" msgid="4527986939729687805">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> amasekhondi</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> amasekhondi</item>
+ </plurals>
+ <plurals name="duration_minutes" formatted="false" msgid="643786953939956125">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> amaminithi</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> amaminithi</item>
+ </plurals>
+ <plurals name="duration_hours" formatted="false" msgid="6826233369186668274">
+ <item quantity="one"><xliff:g id="COUNT">%d</xliff:g> amahora</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> amahora</item>
+ </plurals>
<string name="VideoView_error_title" msgid="3534509135438353077">"Inkinga yevidiyo"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Uxolo, le vidiyo ayilungele ukusakaza bukhomo kwale divaysi."</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"Iyehluleka ukudlala levidiyo."</string>
@@ -1333,14 +1272,14 @@
<string name="ringtone_silent" msgid="7937634392408977062">"Akunalutho"</string>
<string name="ringtone_picker_title" msgid="3515143939175119094">"Amaringithoni"</string>
<string name="ringtone_unknown" msgid="5477919988701784788">"Iringithoni engaziwa"</string>
- <plurals name="wifi_available">
- <item quantity="one" msgid="6654123987418168693">"Inethiwekhi ye-Wi-Fi iyatholakala"</item>
- <item quantity="other" msgid="4192424489168397386">"Amanethiwekhi e-Wi-Fi ayatholakala"</item>
- </plurals>
- <plurals name="wifi_available_detailed">
- <item quantity="one" msgid="1634101450343277345">"Vula inethiwekhi ye-Wi-Fi etholakalayo"</item>
- <item quantity="other" msgid="7915895323644292768">"Vula amanethiwekhi we-Wi-Fi atholakalayo"</item>
- </plurals>
+ <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+ <item quantity="one">Amanethiwekhi we-Wi-Fi ayatholakala</item>
+ <item quantity="other">Amanethiwekhi we-Wi-Fi ayatholakala</item>
+ </plurals>
+ <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+ <item quantity="one">Vula amanethiwekhi we-Wi-Fi atholakalayo</item>
+ <item quantity="other">Vula amanethiwekhi we-Wi-Fi atholakalayo</item>
+ </plurals>
<string name="wifi_available_sign_in" msgid="4029489716605255386">"Ngena enethiwekhini ye-Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="8495155593358054676">"Ngena ngemvume kunethiwekhi"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1416,6 +1355,7 @@
<string name="dlg_ok" msgid="7376953167039865701">"KULUNGILE"</string>
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ixhunyiwe njengedivayisi yemidiya"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ixhunywe njengekhamera"</string>
+ <string name="usb_midi_notification_title" msgid="1399152904227676460">"Kuxhunywe njengedivayisi ye-MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ixhunywe njengesifaki"</string>
<string name="usb_accessory_notification_title" msgid="7848236974087653666">"Ixhunywe ku-accessory ye-USB"</string>
<string name="usb_notification_message" msgid="2290859399983720271">"Cindezela ukuze ubone ezinye izinketho ze-USB"</string>
@@ -1531,10 +1471,10 @@
<string name="skip_button_label" msgid="1275362299471631819">"Yeqa"</string>
<string name="no_matches" msgid="8129421908915840737">"Akukho okufanayo"</string>
<string name="find_on_page" msgid="1946799233822820384">"Thola ekhasini"</string>
- <plurals name="matches_found">
- <item quantity="one" msgid="8167147081136579439">"1 okufanayo"</item>
- <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ku-<xliff:g id="TOTAL">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+ <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> kokungu-<xliff:g id="TOTAL">%d</xliff:g></item>
+ <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> kokungu-<xliff:g id="TOTAL">%d</xliff:g></item>
+ </plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Kwenziwe"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Iyehlisa isitoreji se-USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"Yehlisa ikhadi le-SD..."</string>
@@ -1820,10 +1760,10 @@
<string name="restr_pin_create_pin" msgid="8017600000263450337">"Dala i-PIN yemikhawulo yokushintsha"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Ama-PIN awafani. Zama futhi."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"I-PIN yimfushane kakhulu. Okungenani kumele ibe namadijithi angu-4."</string>
- <plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Zama futhi kusekhondi elingu-1"</item>
- <item quantity="other" msgid="4730868920742952817">"Zama futhi kumasekhondi angu-<xliff:g id="COUNT">%d</xliff:g>"</item>
- </plurals>
+ <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+ <item quantity="one">Zama futhi kumasekhondi angu-<xliff:g id="COUNT">%d</xliff:g></item>
+ <item quantity="other">Zama futhi kumasekhondi angu-<xliff:g id="COUNT">%d</xliff:g></item>
+ </plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Zama futhi emva kwesikhathi"</string>
<string name="immersive_mode_confirmation" msgid="7227416894979047467">"Swayiphela phansi kusukela phezulu ukuze uphume kusikrini esigcwele."</string>
<string name="done_label" msgid="2093726099505892398">"Kwenziwe"</string>
@@ -1849,22 +1789,22 @@
<string name="battery_saver_description" msgid="1960431123816253034">"Ukusiza ukuthuthukisa impilo yebhethri, isilondoloze sebhethri sehlisa ukusebenza kwedivayisi yakho futhi sikhawulele ukudlidliza, amasevisi wendawo, nedatha eningi yangasemuva. I-imeyili, imilayezo, nezinye izinhlelo zokusebenza ezincike ekuvumelaniseni zingahle zingabuyekezwa ngaphandle kokuthi uzivule.\n\nIsilondolozi sebhethri siyavaleka ngokuzenzakalelayo uma idivayisi yakho ishaja."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kuze kuphele isikhathi sakho ngo-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="downtime_condition_line_one" msgid="8762708714645352010">"Kuze kuphele isikhathi sakho sokuphumula"</string>
- <plurals name="zen_mode_duration_minutes_summary">
- <item quantity="one" msgid="3177683545388923234">"Okweminithi elilodwa (kuze kube ngu-<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2787867221129368935">"Okwamaminithi angu-%1$d (kuze kube ngu-<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours_summary">
- <item quantity="one" msgid="597194865053253679">"Okwehora elilodwa (kuze kube ngu-<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- <item quantity="other" msgid="2827214920627669898">"Ngamahora angu-%1$d (kuze kube ngu-<xliff:g id="FORMATTEDTIME">%2$s</xliff:g>)"</item>
- </plurals>
- <plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"Iminithi elilodwa"</item>
- <item quantity="other" msgid="6924190729213550991">"Amaminithi angu-%d"</item>
- </plurals>
- <plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"Ihora elilodwa"</item>
- <item quantity="other" msgid="5408537517529822157">"Amahora angu-%d"</item>
- </plurals>
+ <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+ <item quantity="one">Okwamaminithi angu-%1$d (kuze kube ngo-<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Okwamaminithi angu-%1$d (kuze kube ngo-<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+ <item quantity="one">Kwamahora angu-%1$d (kuze kube ngo-<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ <item quantity="other">Kwamahora angu-%1$d (kuze kube ngo-<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+ </plurals>
+ <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+ <item quantity="one">Amaminithi angu-%d</item>
+ <item quantity="other">Amaminithi angu-%d</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+ <item quantity="one">Amahora angu-%d</item>
+ <item quantity="other">Amahora angu-%d</item>
+ </plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="4316804956488785559">"Unaphakade"</string>
<string name="toolbar_collapse_description" msgid="2821479483960330739">"Goqa"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b90ac65..09103e3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -329,7 +329,9 @@
<attr name="windowOverscan" format="boolean" />
<!-- Flag indicating whether this is a floating window. -->
<attr name="windowIsFloating" format="boolean" />
- <!-- Flag indicating whether this is a translucent window. -->
+ <!-- Flag indicating whether this is a translucent window. If this attribute is unset (but
+ not if set to false), the window might still be considered translucent, if
+ windowSwipeToDismiss is set to true. -->
<attr name="windowIsTranslucent" format="boolean" />
<!-- Flag indicating that this window's background should be the
user's current wallpaper. Corresponds
@@ -455,7 +457,9 @@
<attr name="windowTranslucentNavigation" format="boolean" />
<!-- Flag to indicate that a window can be swiped away to be dismissed.
- Corresponds to {@link android.view.Window#FEATURE_SWIPE_TO_DISMISS} -->
+ Corresponds to {@link android.view.Window#FEATURE_SWIPE_TO_DISMISS}. It will also
+ dynamically change translucency of the window, if the windowIsTranslucent is not set.
+ If windowIsTranslucent is set (to either true or false) it will obey that setting. -->
<attr name="windowSwipeToDismiss" format="boolean" />
<!-- Flag indicating whether this window requests that content changes be performed
@@ -4778,6 +4782,8 @@
<attr name="headerBackground" />
<!-- The color for the hours/minutes numbers. -->
<attr name="numbersTextColor" format="color" />
+ <!-- The color for the inner hours numbers used in 24-hour mode. -->
+ <attr name="numbersInnerTextColor" format="color" />
<!-- The background color for the hours/minutes numbers. -->
<attr name="numbersBackgroundColor" format="color" />
<!-- The color for the AM/PM selectors. -->
@@ -5291,6 +5297,9 @@
<declare-styleable name="RippleDrawable">
<!-- The color to use for ripple effects. This attribute is required. -->
<attr name="color" />
+ <!-- The radius of the ripple when fully expanded. By default, the
+ radius is computed based on the size of the ripple's container. -->
+ <attr name="radius" />
</declare-styleable>
<declare-styleable name="ScaleDrawable">
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 457131a..7c63950 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -25,4 +25,8 @@
<bool name="show_ongoing_ime_switcher">true</bool>
<bool name="action_bar_expanded_action_views_exclusive">true</bool>
<bool name="target_honeycomb_needs_options_menu">true</bool>
+
+ <!-- Whether to allow vertically stacked button bars. This is disabled for
+ configurations with a small (e.g. less than 320dp) screen height. -->
+ <bool name="allow_stacked_button_bar">false</bool>
</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 8dad63e..93f58cba 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -25,8 +25,11 @@
<color name="primary_material_light">#ffefefef</color>
<color name="primary_dark_material_dark">#ff000000</color>
<color name="primary_dark_material_light">#ff757575</color>
+ <color name="primary_dark_material_light_light_status_bar">#ffe0e0e0</color>
- <color name="ripple_material_dark">#4dffffff</color>
+ <!-- 26% white (foreground) -->
+ <color name="ripple_material_dark">#42ffffff</color>
+ <!-- 12% black (foreground) -->
<color name="ripple_material_light">#1f000000</color>
<color name="accent_material_light">@color/material_deep_teal_500</color>
@@ -42,9 +45,9 @@
<color name="bright_foreground_material_dark">@color/white</color>
<color name="bright_foreground_material_light">@color/black</color>
- <!-- White 50% -->
+ <!-- 50% white (foreground) -->
<color name="bright_foreground_disabled_material_dark">#80ffffff</color>
- <!-- Black 50% -->
+ <!-- 50% black (foreground) -->
<color name="bright_foreground_disabled_material_light">#80000000</color>
<color name="bright_foreground_inverse_material_dark">@color/bright_foreground_material_light</color>
<color name="bright_foreground_inverse_material_light">@color/bright_foreground_material_dark</color>
@@ -57,11 +60,6 @@
<color name="hint_foreground_material_dark">@color/bright_foreground_disabled_material_dark</color>
<color name="hint_foreground_material_light">@color/bright_foreground_disabled_material_light</color>
- <!-- TODO: This is 40% alpha on the default accent color. -->
- <color name="highlighted_text_material_dark">#6680cbc4</color>
- <!-- TODO: This is 40% alpha on the default accent color. -->
- <color name="highlighted_text_material_light">#66009688</color>
-
<color name="link_text_material_dark">@color/material_deep_teal_200</color>
<color name="link_text_material_light">@color/material_deep_teal_500</color>
@@ -77,6 +75,10 @@
<item name="disabled_alpha_material_light" format="float" type="dimen">0.26</item>
<item name="disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
+ <item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
+ <item name="highlight_alpha_material_dark" format="float" type="dimen">0.20</item>
+ <item name="highlight_alpha_material_colored" format="float" type="dimen">0.26</item>
+
<!-- Primary & accent colors -->
<eat-comment />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f2d9de8..4c0520e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -632,6 +632,14 @@
Any other values will have surprising consequences. -->
<integer name="config_defaultUiModeType">1</integer>
+ <!-- Control the default night mode to use when there is no other mode override set.
+ One of the following values (see UiModeManager.java):
+ 0 - MODE_NIGHT_AUTO
+ 1 - MODE_NIGHT_NO
+ 2 - MODE_NIGHT_YES
+ -->
+ <integer name="config_defaultNightMode">1</integer>
+
<!-- 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.
@@ -861,10 +869,34 @@
<!-- Allow automatic adjusting of the screen brightness while dozing in low power state. -->
<bool name="config_allowAutoBrightnessWhileDozing">false</bool>
+ <!-- Stability requirements in milliseconds for accepting a new brightness level. This is used
+ for debouncing the light sensor. Different constants are used to debounce the light sensor
+ when adapting to brighter or darker environments. This parameter controls how quickly
+ brightness changes occur in response to an observed change in light level that exceeds the
+ hysteresis threshold. -->
+ <integer name="config_autoBrightnessBrighteningLightDebounce">4000</integer>
+ <integer name="config_autoBrightnessDarkeningLightDebounce">8000</integer>
+
+ <!-- Light sensor event rate in milliseconds for automatic brightness control. -->
+ <integer name="config_autoBrightnessLightSensorRate">250</integer>
+
<!-- If we allow automatic adjustment of screen brightness while dozing, how many times we want
to reduce it to preserve the battery. Value of 100% means no scaling. -->
<fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>
+ <!-- When the screen is turned on, the previous estimate of the ambient light level at the time
+ the screen was turned off is restored and is used to determine the initial screen
+ brightness.
+
+ If this flag is true, then the ambient light level estimate will be promptly recomputed
+ after the warm-up interface and the screen brightness will be adjusted immediately.
+
+ If this flag is false, then the ambient light level estimate will be adjusted more
+ gradually in the same manner that normally happens when the screen is on according to the
+ brightening or dimming debounce thresholds. As a result, it may take somewhat longer to
+ adapt to the environment. This mode may be better suited for watches. -->
+ <bool name="config_autoBrightnessResetAmbientLuxAfterWarmUp">true</bool>
+
<!-- Screen brightness used to dim the screen when the user activity
timeout expires. May be less than the minimum allowed brightness setting
that can be set by the user. -->
@@ -1820,6 +1852,12 @@
<item>users</item>
</string-array>
+ <!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
+ flushed to the display while dozing. This value needs to be large enough
+ to account for processing and rendering time plus a frame or two of latency
+ in the display pipeline plus some slack just to be sure. -->
+ <integer name="config_drawLockTimeoutMillis">120</integer>
+
<!-- default telephony hardware configuration for this platform.
-->
<!-- this string array should be overridden by the device to present a list
@@ -2028,4 +2066,12 @@
<!-- Whether to start in touch mode -->
<bool name="config_defaultInTouchMode">true</bool>
+
+ <!-- Time adjustment, in milliseconds, applied to the default double tap threshold
+ used for gesture detection by the screen magnifier. -->
+ <integer name="config_screen_magnification_multi_tap_adjustment">-50</integer>
+
+ <!-- Scale factor threshold used by the screen magnifier to determine when to switch from
+ panning to scaling the magnification viewport. -->
+ <item name="config_screen_magnification_scaling_threshold" format="float" type="dimen">0.3</item>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 68a3493..d240047 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -31,7 +31,7 @@
<integer name="max_action_buttons">2</integer>
<dimen name="toast_y_offset">64dip</dimen>
<!-- Height of the status bar -->
- <dimen name="status_bar_height">25dip</dimen>
+ <dimen name="status_bar_height">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
@@ -304,6 +304,9 @@
<!-- Touch slop for the global toggle accessibility gesture -->
<dimen name="accessibility_touch_slop">80dip</dimen>
+ <!-- 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>
@@ -354,26 +357,23 @@
<dimen name="subtitle_outline_width">2dp</dimen>
<!-- New TimePicker dimensions. -->
- <item name="timepicker_selection_radius_multiplier" format="float" type="dimen">0.16</item>
- <item name="timepicker_numbers_radius_multiplier_normal" format="float" type="dimen">0.81</item>
- <item name="timepicker_numbers_radius_multiplier_inner" format="float" type="dimen">0.60</item>
- <item name="timepicker_numbers_radius_multiplier_outer" format="float" type="dimen">0.83</item>
- <item name="timepicker_text_size_multiplier_normal" format="float" type="dimen">0.17</item>
- <item name="timepicker_text_size_multiplier_inner" format="float" type="dimen">0.14</item>
- <item name="timepicker_text_size_multiplier_outer" format="float" type="dimen">0.11</item>
- <item name="timepicker_transition_mid_radius_multiplier" format="float" type="dimen">0.95</item>
- <item name="timepicker_transition_end_radius_multiplier" format="float" type="dimen">1.3</item>
+ <dimen name="timepicker_selector_radius">24dp</dimen>
+ <dimen name="timepicker_center_dot_radius">4dp</dimen>
+ <dimen name="timepicker_selector_dot_radius">4dp</dimen>
+ <dimen name="timepicker_text_inset_normal">26dp</dimen>
+ <dimen name="timepicker_text_inset_inner">58dp</dimen>
+ <dimen name="timepicker_text_size_normal">14sp</dimen>
+ <dimen name="timepicker_text_size_inner">12sp</dimen>
- <dimen name="timepicker_time_label_size">60sp</dimen>
- <dimen name="timepicker_extra_time_label_margin">-30dp</dimen>
+ <!-- Text size for the time picker header HH:MM label. This value is large
+ enough that we don't need to use scaled pixels, dp is fine. -->
+ <dimen name="timepicker_time_label_size">60dp</dimen>
<dimen name="timepicker_ampm_label_size">16sp</dimen>
<dimen name="timepicker_ampm_horizontal_padding">12dp</dimen>
<dimen name="timepicker_ampm_vertical_padding">16dp</dimen>
<dimen name="timepicker_pm_top_padding">3dp</dimen>
<dimen name="timepicker_separator_padding">4dp</dimen>
<dimen name="timepicker_header_height">96dp</dimen>
- <dimen name="timepicker_minimum_margin_sides">48dp</dimen>
- <dimen name="timepicker_minimum_margin_top_bottom">24dp</dimen>
<dimen name="timepicker_radial_picker_dimen">270dp</dimen>
<!-- Used by SimpleMonthView -->
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 1975875..b84249a 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -23,7 +23,7 @@
<dimen name="preference_screen_side_margin_negative_material">0dp</dimen>
<!-- Preference fragment padding, sides -->
- <dimen name="preference_fragment_padding_side_material">8dp</dimen>
+ <dimen name="preference_fragment_padding_side_material">0dp</dimen>
<!-- Preference breadcrumbs padding, start padding -->
<dimen name="preference_breadcrumbs_padding_start_material">12dp</dimen>
@@ -115,5 +115,6 @@
<!-- Padding above and below selection dialog lists. -->
<dimen name="dialog_list_padding_vertical_material">8dp</dimen>
+ <dimen name="scrubber_track_height_material">2dp</dimen>
<dimen name="progress_bar_height_material">4dp</dimen>
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bd24f3e..b6e79ad 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -89,4 +89,7 @@
<item type="id" name="parentMatrix" />
<item type="id" name="statusBarBackground" />
<item type="id" name="navigationBarBackground" />
+ <item type="id" name="undo" />
+ <item type="id" name="redo" />
+ <item type="id" name="pasteAsPlainText" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e2a0ec9..af4922f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2614,7 +2614,33 @@
<public type="attr" name="start" />
<public type="attr" name="end" />
<public type="attr" name="windowHasLightStatusBar" />
+ <public type="attr" name="numbersInnerTextColor" />
<public type="style" name="Widget.Material.Button.Colored" />
+ <public type="style" name="Theme.Material.DayNight" />
+ <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
+ <public type="style" name="Theme.Material.DayNight.Dialog" />
+ <public type="style" name="Theme.Material.DayNight.Dialog.Alert" />
+ <public type="style" name="Theme.Material.DayNight.Dialog.MinWidth" />
+ <public type="style" name="Theme.Material.DayNight.Dialog.NoActionBar" />
+ <public type="style" name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" />
+ <public type="style" name="Theme.Material.DayNight.Dialog.Presentation" />
+ <public type="style" name="Theme.Material.DayNight.DialogWhenLarge" />
+ <public type="style" name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" />
+ <public type="style" name="Theme.Material.DayNight.NoActionBar" />
+ <public type="style" name="Theme.Material.DayNight.NoActionBar.Fullscreen" />
+ <public type="style" name="Theme.Material.DayNight.NoActionBar.Overscan" />
+ <public type="style" name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" />
+ <public type="style" name="Theme.Material.DayNight.Panel" />
+ <public type="style" name="Theme.Material.Light.LightStatusBar" />
+
+ <!-- Context menu ID for the "Undo" menu item to undo the last text edit operation. -->
+ <public type="id" name="undo" />
+ <!-- Context menu ID for the "Redo" menu item to redo the last text edit operation. -->
+ <public type="id" name="redo" />
+ <!-- Context menu ID for the "Paste as plain text" menu item to to copy the current contents
+ of the clipboard into the text view without formatting. -->
+ <public type="id" name="pasteAsPlainText" />
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9946ce8..199b783 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2396,7 +2396,7 @@
<!-- Title of policy access to limiting the user's password choices -->
<string name="policylab_limitPassword">Set password rules</string>
<!-- Description of policy access to limiting the user's password choices -->
- <string name="policydesc_limitPassword">Control the length and the characters allowed in screen-unlock passwords.</string>
+ <string name="policydesc_limitPassword">Control the length and the characters allowed in screen lock passwords and PINs.</string>
<!-- Title of policy access to watch user login attempts -->
<string name="policylab_watchLogin">Monitor screen-unlock attempts</string>
<!-- Description of policy access to watch user login attempts -->
@@ -2411,15 +2411,24 @@
<string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords
typed. when unlocking the screen, and lock the phone or erase all the phone\'s
data if too many incorrect passwords are typed.</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet">Monitor the number of incorrect passwords
+ typed when unlocking the screen, and lock the tablet or erase all this user\'s data
+ if too many incorrect passwords are typed.</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV">Monitor the number of incorrect passwords
+ typed when unlocking the screen, and lock the TV or erase all this user\'s data
+ if too many incorrect passwords are typed.</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default">Monitor the number of incorrect passwords
+ typed when unlocking the screen, and lock the phone or erase all this user\'s data
+ if too many incorrect passwords are typed.</string>
<!-- Title of policy access to reset user's password -->
- <string name="policylab_resetPassword">Change the screen-unlock password</string>
+ <string name="policylab_resetPassword">Change the screen lock</string>
<!-- Description of policy access to reset user's password -->
- <string name="policydesc_resetPassword">Change the screen-unlock password.</string>
+ <string name="policydesc_resetPassword">Change the screen lock.</string>
<!-- Title of policy access to force lock the device -->
<string name="policylab_forceLock">Lock the screen</string>
<!-- Description of policy access to limiting the user's password choices -->
<string name="policydesc_forceLock">Control how and when the screen locks.</string>
- <!-- Title of policy access to wipe the user's data -->
+ <!-- Title of policy access to wipe primary user's data -->
<string name="policylab_wipeData">Erase all data</string>
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData" product="tablet">Erase the tablet\'s data without warning by performing a factory data reset.</string>
@@ -2427,15 +2436,23 @@
<string name="policydesc_wipeData" product="tv">Erase the TV\'s data without warning by performing a factory data reset.</string>
<!-- Description of policy access to wipe the user's data -->
<string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning by performing a factory data reset.</string>
- <string name="policylab_setGlobalProxy">Set the device global proxy</string>
+ <!-- Title of policy access to wipe secondary user's data -->
+ <string name="policylab_wipeData_secondaryUser">Erase user data</string>
<!-- Description of policy access to wipe the user's data -->
+ <string name="policydesc_wipeData_secondaryUser" product="tablet">Erase this user\'s data on this tablet without warning.</string>
+ <!-- Description of policy access to wipe the user's data -->
+ <string name="policydesc_wipeData_secondaryUser" product="tv">Erase this user\'s data on this TV without warning.</string>
+ <!-- Description of policy access to wipe the user's data -->
+ <string name="policydesc_wipeData_secondaryUser" product="default">Erase this user\'s data on this phone without warning.</string>
+ <!-- Title of policy access to set global proxy -->
+ <string name="policylab_setGlobalProxy">Set the device global proxy</string>
+ <!-- Description of policy access to set global proxy -->
<string name="policydesc_setGlobalProxy">Set the device global proxy
- to be used while policy is enabled. Only the first device admin
- sets the effective global proxy.</string>
+ to be used while policy is enabled. Only the device owner can set the global proxy.</string>
<!-- Title of policy access to enforce password expiration [CHAR LIMIT=30]-->
- <string name="policylab_expirePassword">Set lock-screen password expiration</string>
+ <string name="policylab_expirePassword">Set screen lock password expiration</string>
<!-- Description of policy access to enforce password expiration [CHAR LIMIT=110]-->
- <string name="policydesc_expirePassword">Control how frequently the lock-screen password must be changed.</string>
+ <string name="policydesc_expirePassword">Change how frequently the screen lock password, PIN, or pattern must be changed.</string>
<!-- Title of policy access to require encrypted storage [CHAR LIMIT=30]-->
<string name="policylab_encryptedStorage">Set storage encryption</string>
<!-- Description of policy access to require encrypted storage [CHAR LIMIT=110]-->
@@ -2445,9 +2462,9 @@
<!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
<string name="policydesc_disableCamera">Prevent use of all device cameras.</string>
<!-- Title of policy access to disable all device cameras [CHAR LIMIT=30]-->
- <string name="policylab_disableKeyguardFeatures">Disable features in keyguard</string>
+ <string name="policylab_disableKeyguardFeatures">Disable features of screen lock</string>
<!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]-->
- <string name="policydesc_disableKeyguardFeatures">Prevent use of some features in keyguard.</string>
+ <string name="policydesc_disableKeyguardFeatures">Prevent use of some features of screen lock.</string>
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
@@ -3380,24 +3397,6 @@
<!-- String used to display the date. This is the string to say something happened more than 1 month ago. -->
<string name="beforeOneMonthDurationPast">Before 1 month ago</string>
- <!-- This is used to express that something occurred some number of seconds in the past (e.g., 5 seconds ago). -->
- <plurals name="num_seconds_ago">
- <item quantity="one">1 second ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> seconds ago</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of minutes in the past (e.g., 5 minutes ago). -->
- <plurals name="num_minutes_ago">
- <item quantity="one">1 minute ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> minutes ago</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of hours in the past (e.g., 5 hours ago). -->
- <plurals name="num_hours_ago">
- <item quantity="one">1 hour ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> hours ago</item>
- </plurals>
-
<!-- This is used to express that something occurred within the last X days (e.g., Last 7 days). -->
<plurals name="last_num_days">
<item quantity="one">Last <xliff:g id="count">%d</xliff:g> day</item>
@@ -3410,84 +3409,6 @@
<!-- This is used to express that something happened longer ago than the previous options -->
<string name="older">Older</string>
- <!-- This is used to express that something occurred some number of days in the past (e.g., 5 days ago). -->
- <plurals name="num_days_ago">
- <item quantity="one">yesterday</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> days ago</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of seconds in the future (e.g., in 5 seconds). -->
- <plurals name="in_num_seconds">
- <item quantity="one">in 1 second</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> seconds</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of minutes in the future (e.g., in 5 minutes). -->
- <plurals name="in_num_minutes">
- <item quantity="one">in 1 minute</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> minutes</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of hours in the future (e.g., in 5 hours). -->
- <plurals name="in_num_hours">
- <item quantity="one">in 1 hour</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> hours</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of days in the future (e.g., in 5 days). -->
- <plurals name="in_num_days">
- <item quantity="one">tomorrow</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> days</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of abbreviated seconds in the past (e.g., 5 secs ago). -->
- <plurals name="abbrev_num_seconds_ago">
- <item quantity="one">1 sec ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> secs ago</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of abbreviated minutes in the past (e.g., 5 mins ago). -->
- <plurals name="abbrev_num_minutes_ago">
- <item quantity="one">1 min ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> mins ago</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of abbreviated hours in the past (e.g., 5 hrs ago). -->
- <plurals name="abbrev_num_hours_ago">
- <item quantity="one">1 hour ago</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> hours ago</item>
- </plurals>
-
- <!-- This is used to express that something occurred some number of abbreviated days in the past (e.g., 5 days ago). -->
- <plurals name="abbrev_num_days_ago">
- <item quantity="one">yesterday</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> days ago</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of abbreviated seconds in the future (e.g., in 5 secs). -->
- <plurals name="abbrev_in_num_seconds">
- <item quantity="one">in 1 sec</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> secs</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of abbreviated minutes in the future (e.g., in 5 mins). -->
- <plurals name="abbrev_in_num_minutes">
- <item quantity="one">in 1 min</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> mins</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of abbreviated hours in the future (e.g., in 5 hrs). -->
- <plurals name="abbrev_in_num_hours">
- <item quantity="one">in 1 hour</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> hours</item>
- </plurals>
-
- <!-- This is used to express that something will occur some number of abbreviated days in the future (e.g., in 5 days). -->
- <plurals name="abbrev_in_num_days">
- <item quantity="one">tomorrow</item>
- <item quantity="other">in <xliff:g id="count">%d</xliff:g> days</item>
- </plurals>
-
<!-- String used to display the date. Preposition for date display ("on May 29") -->
<string name="preposition_for_date">on <xliff:g id="date" example="May 29">%s</xliff:g></string>
<!-- String used to display the date. Preposition for time display ("at 2:33am") -->
@@ -4005,6 +3926,8 @@
<string name="usb_mtp_notification_title">Connected as a media device</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in PTP mode. This is the title -->
<string name="usb_ptp_notification_title">Connected as a camera</string>
+ <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title -->
+ <string name="usb_midi_notification_title">Connected as a MIDI device</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in mass storage mode (for installer CD image). This is the title -->
<string name="usb_cd_installer_notification_title">Connected as an installer</string>
<!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title -->
@@ -5167,7 +5090,7 @@
<string name="zen_mode_until">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_forever">Indefinitely</string>
+ <string name="zen_mode_forever">Until you turn this off</string>
<!-- Content description for the Toolbar icon used to collapse an expanded action mode. [CHAR LIMIT=NONE] -->
<string name="toolbar_collapse_description">Collapse</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 777924f..d75e496 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -306,7 +306,9 @@
<item name="textColor">?attr/textColorPrimary</item>
</style>
- <style name="TextAppearance.Material.Widget.TabWidget" parent="TextAppearance.Material.Button" />
+ <style name="TextAppearance.Material.Widget.TabWidget" parent="TextAppearance.Material.Button">
+ <item name="textColor">@color/tab_indicator_text_material</item>
+ </style>
<style name="TextAppearance.Material.Widget.TextView">
<item name="textColor">?attr/textColorPrimaryDisableOnly</item>
@@ -651,7 +653,8 @@
<item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
<item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
<item name="headerBackground">@drawable/time_picker_header_material</item>
- <item name="numbersTextColor">?attr/textColorSecondaryActivated</item>
+ <item name="numbersTextColor">?attr/textColorPrimaryActivated</item>
+ <item name="numbersInnerTextColor">?attr/textColorSecondaryActivated</item>
<item name="numbersBackgroundColor">#10ffffff</item>
<item name="numbersSelectorColor">?attr/colorControlActivated</item>
<item name="amPmTextColor">?attr/textColorSecondary</item>
@@ -788,12 +791,16 @@
<item name="background">@drawable/spinner_textfield_background_material</item>
</style>
- <style name="Widget.Material.TabWidget" parent="Widget.TabWidget">
- <item name="tabStripLeft">@null</item>
- <item name="tabStripRight">@null</item>
+ <style name="Widget.Material.TabWidget">
+ <item name="textAppearance">@style/TextAppearance.Material.Widget.TabWidget</item>
+ <item name="ellipsize">marquee</item>
+ <item name="singleLine">true</item>
+ <item name="tabStripLeft">@empty</item>
+ <item name="tabStripRight">@empty</item>
<item name="tabStripEnabled">false</item>
<item name="divider">?attr/dividerVertical</item>
- <item name="showDividers">middle</item>
+ <item name="gravity">fill_horizontal|center_vertical</item>
+ <item name="showDividers">none</item>
<item name="dividerPadding">8dip</item>
<item name="measureWithLargestChild">true</item>
<item name="tabLayout">@layout/tab_indicator_material</item>
@@ -816,19 +823,21 @@
<item name="subtitleTextAppearance">@style/TextAppearance.Material.Widget.Toolbar.Subtitle</item>
</style>
- <style name="Widget.Material.Toolbar.Button.Navigation" parent="Widget.Toolbar.Button.Navigation">
+ <style name="Widget.Material.Toolbar.Button.Navigation" parent="Widget.Material">
<item name="background">?attr/controlBackground</item>
+ <item name="minWidth">56dp</item>
+ <item name="scaleType">center</item>
<item name="paddingStart">@dimen/action_bar_navigation_padding_start_material</item>
</style>
<style name="Widget.Material.WebTextView" parent="Widget.WebTextView"/>
-
<style name="Widget.Material.WebView" parent="Widget.WebView"/>
- <style name="Widget.Material.DropDownItem" parent="Widget.DropDownItem">
+ <style name="Widget.Material.DropDownItem">
<item name="textAppearance">@style/TextAppearance.Material.Widget.DropDownItem</item>
<item name="paddingStart">8dp</item>
<item name="paddingEnd">8dp</item>
+ <item name="gravity">center_vertical</item>
</style>
<style name="Widget.Material.DropDownItem.Spinner"/>
@@ -841,7 +850,7 @@
<style name="Widget.Material.QuickContactBadgeSmall.WindowMedium" parent="Widget.QuickContactBadgeSmall.WindowMedium"/>
<style name="Widget.Material.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
- <style name="Widget.Material.ListPopupWindow" parent="Widget.ListPopupWindow">
+ <style name="Widget.Material.ListPopupWindow">
<item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
<item name="popupBackground">@drawable/popup_background_material</item>
<item name="popupElevation">@dimen/floating_window_z</item>
@@ -860,14 +869,15 @@
<item name="dropDownHorizontalOffset">-4dip</item>
</style>
- <style name="Widget.Material.ActionButton" parent="Widget.ActionButton">
+ <style name="Widget.Material.ActionButton">
+ <item name="background">?attr/actionBarItemBackground</item>
+ <item name="paddingStart">12dp</item>
+ <item name="paddingEnd">12dp</item>
<item name="minWidth">@dimen/action_button_min_width_material</item>
<item name="minHeight">@dimen/action_button_min_height_material</item>
<item name="gravity">center</item>
<item name="scaleType">center</item>
<item name="maxLines">2</item>
- <item name="paddingStart">12dp</item>
- <item name="paddingEnd">12dp</item>
</style>
<style name="Widget.Material.ActionButton.CloseMode">
@@ -884,34 +894,36 @@
<item name="paddingEnd">@dimen/action_bar_overflow_padding_end_material</item>
</style>
- <style name="Widget.Material.ActionBar.TabView" parent="Widget.ActionBar.TabView">
+ <style name="Widget.Material.ActionBar.TabView" parent="Widget.Material">
+ <item name="gravity">center_horizontal</item>
<item name="background">@drawable/tab_indicator_material</item>
<item name="paddingStart">16dip</item>
<item name="paddingEnd">16dip</item>
</style>
- <style name="Widget.Material.ActionBar.TabBar" parent="Widget.ActionBar.TabBar">
+ <style name="Widget.Material.ActionBar.TabBar" parent="Widget.Material">
<item name="divider">?attr/actionBarDivider</item>
<item name="showDividers">middle</item>
<item name="dividerPadding">12dip</item>
</style>
- <style name="Widget.Material.ActionBar.TabText" parent="Widget.ActionBar.TabText">
- <item name="textAppearance">@style/TextAppearance.Material.Medium</item>
- <item name="textColor">?attr/textColorPrimary</item>
- <item name="textSize">12sp</item>
- <item name="textStyle">bold</item>
- <item name="textAllCaps">true</item>
+ <style name="Widget.Material.ActionBar.TabText">
+ <item name="textAppearance">@style/TextAppearance.Material.Widget.TabWidget</item>
<item name="ellipsize">marquee</item>
<item name="maxLines">2</item>
</style>
- <style name="Widget.Material.ActionBar" parent="Widget.ActionBar">
+ <style name="Widget.Material.ActionBar">
<item name="background">@null</item>
<item name="backgroundStacked">@null</item>
<item name="backgroundSplit">@null</item>
<item name="displayOptions">showTitle</item>
<item name="divider">?attr/dividerVertical</item>
+ <item name="height">?attr/actionBarSize</item>
+ <item name="paddingStart">0dip</item>
+ <item name="paddingTop">0dip</item>
+ <item name="paddingEnd">0dip</item>
+ <item name="paddingBottom">0dip</item>
<item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionBar.Subtitle</item>
<item name="progressBarStyle">?attr/progressBarStyleHorizontal</item>
@@ -932,19 +944,28 @@
<item name="backgroundSplit">?attr/colorPrimary</item>
</style>
- <style name="Widget.Material.ActionMode" parent="Widget.ActionMode">
+ <style name="Widget.Material.ActionMode">
+ <item name="background">?attr/actionModeBackground</item>
+ <item name="backgroundSplit">?attr/actionModeSplitBackground</item>
+ <item name="height">?attr/actionBarSize</item>
<item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Subtitle</item>
<item name="closeItemLayout">@layout/action_mode_close_item_material</item>
</style>
- <style name="Widget.Material.FastScroll" parent="Widget.FastScroll">
+ <style name="Widget.Material.FastScroll">
+ <item name="thumbDrawable">?attr/fastScrollThumbDrawable</item>
+ <item name="trackDrawable">?attr/fastScrollTrackDrawable</item>
+ <item name="backgroundLeft">?attr/fastScrollPreviewBackgroundLeft</item>
+ <item name="backgroundRight">?attr/fastScrollPreviewBackgroundRight</item>
+ <item name="position">?attr/fastScrollOverlayPosition</item>
+ <item name="textColor">?attr/fastScrollTextColor</item>
<item name="thumbMinWidth">0dp</item>
<item name="thumbMinHeight">0dp</item>
+ <item name="textSize">45sp</item>
<item name="minWidth">88dp</item>
<item name="minHeight">88dp</item>
<item name="padding">0dp</item>
- <item name="textSize">45sp</item>
</style>
<style name="Widget.Material.PreferenceFrameLayout">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 813de7c..aad3e96 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -345,6 +345,7 @@
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
<java-symbol type="integer" name="config_cursorWindowSize" />
+ <java-symbol type="integer" name="config_drawLockTimeoutMillis" />
<java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
<java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
@@ -412,6 +413,7 @@
<java-symbol type="dimen" name="notification_badge_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
<java-symbol type="dimen" name="circular_display_mask_offset" />
+ <java-symbol type="dimen" name="accessibility_magnification_indicator_width" />
<java-symbol type="string" name="add_account_button_label" />
<java-symbol type="string" name="addToDictionary" />
@@ -752,7 +754,9 @@
<java-symbol type="string" name="policydesc_resetPassword" />
<java-symbol type="string" name="policydesc_setGlobalProxy" />
<java-symbol type="string" name="policydesc_watchLogin" />
+ <java-symbol type="string" name="policydesc_watchLogin_secondaryUser" />
<java-symbol type="string" name="policydesc_wipeData" />
+ <java-symbol type="string" name="policydesc_wipeData_secondaryUser" />
<java-symbol type="string" name="policydesc_disableKeyguardFeatures" />
<java-symbol type="string" name="policylab_disableCamera" />
<java-symbol type="string" name="policylab_encryptedStorage" />
@@ -763,6 +767,7 @@
<java-symbol type="string" name="policylab_setGlobalProxy" />
<java-symbol type="string" name="policylab_watchLogin" />
<java-symbol type="string" name="policylab_wipeData" />
+ <java-symbol type="string" name="policylab_wipeData_secondaryUser" />
<java-symbol type="string" name="policylab_disableKeyguardFeatures" />
<java-symbol type="string" name="postalTypeCustom" />
<java-symbol type="string" name="postalTypeHome" />
@@ -1057,27 +1062,11 @@
<java-symbol type="string" name="config_ethernet_tcp_buffers" />
<java-symbol type="string" name="config_wifi_tcp_buffers" />
- <java-symbol type="plurals" name="abbrev_in_num_days" />
- <java-symbol type="plurals" name="abbrev_in_num_hours" />
- <java-symbol type="plurals" name="abbrev_in_num_minutes" />
- <java-symbol type="plurals" name="abbrev_in_num_seconds" />
- <java-symbol type="plurals" name="abbrev_num_days_ago" />
- <java-symbol type="plurals" name="abbrev_num_hours_ago" />
- <java-symbol type="plurals" name="abbrev_num_minutes_ago" />
- <java-symbol type="plurals" name="abbrev_num_seconds_ago" />
<java-symbol type="plurals" name="duration_hours" />
<java-symbol type="plurals" name="duration_minutes" />
<java-symbol type="plurals" name="duration_seconds" />
- <java-symbol type="plurals" name="in_num_days" />
- <java-symbol type="plurals" name="in_num_hours" />
- <java-symbol type="plurals" name="in_num_minutes" />
- <java-symbol type="plurals" name="in_num_seconds" />
<java-symbol type="plurals" name="last_num_days" />
<java-symbol type="plurals" name="matches_found" />
- <java-symbol type="plurals" name="num_days_ago" />
- <java-symbol type="plurals" name="num_hours_ago" />
- <java-symbol type="plurals" name="num_minutes_ago" />
- <java-symbol type="plurals" name="num_seconds_ago" />
<java-symbol type="plurals" name="restr_pin_countdown" />
<java-symbol type="plurals" name="pinpuk_attempts" />
@@ -1588,6 +1577,7 @@
<java-symbol type="bool" name="config_useAttentionLight" />
<java-symbol type="bool" name="config_animateScreenLights" />
<java-symbol type="bool" name="config_automatic_brightness_available" />
+ <java-symbol type="bool" name="config_autoBrightnessResetAmbientLuxAfterWarmUp" />
<java-symbol type="bool" name="config_dozeAfterScreenOff" />
<java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
<java-symbol type="bool" name="config_enableFusedLocationOverlay" />
@@ -1643,6 +1633,9 @@
<java-symbol type="id" name="replace_message" />
<java-symbol type="fraction" name="config_dimBehindFadeDuration" />
<java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+ <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
+ <java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
+ <java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
<java-symbol type="integer" name="config_carDockKeepsScreenOn" />
<java-symbol type="integer" name="config_criticalBatteryWarningLevel" />
<java-symbol type="integer" name="config_datause_notification_type" />
@@ -1761,6 +1754,7 @@
<java-symbol type="string" name="usb_notification_message" />
<java-symbol type="string" name="use_physical_keyboard" />
<java-symbol type="string" name="usb_ptp_notification_title" />
+ <java-symbol type="string" name="usb_midi_notification_title" />
<java-symbol type="string" name="vpn_text" />
<java-symbol type="string" name="vpn_text_long" />
<java-symbol type="string" name="vpn_title" />
@@ -2007,15 +2001,13 @@
<java-symbol type="string" name="deleted_key" />
<java-symbol type="string" name="sans_serif" />
<java-symbol type="string" name="radial_numbers_typeface" />
- <java-symbol type="dimen" name="timepicker_text_size_multiplier_inner" />
- <java-symbol type="dimen" name="timepicker_text_size_multiplier_outer" />
- <java-symbol type="dimen" name="timepicker_text_size_multiplier_normal" />
- <java-symbol type="dimen" name="timepicker_numbers_radius_multiplier_outer" />
- <java-symbol type="dimen" name="timepicker_selection_radius_multiplier" />
- <java-symbol type="dimen" name="timepicker_numbers_radius_multiplier_inner" />
- <java-symbol type="dimen" name="timepicker_numbers_radius_multiplier_normal" />
- <java-symbol type="dimen" name="timepicker_transition_mid_radius_multiplier" />
- <java-symbol type="dimen" name="timepicker_transition_end_radius_multiplier" />
+ <java-symbol type="dimen" name="timepicker_selector_radius" />
+ <java-symbol type="dimen" name="timepicker_selector_dot_radius" />
+ <java-symbol type="dimen" name="timepicker_center_dot_radius" />
+ <java-symbol type="dimen" name="timepicker_text_inset_normal" />
+ <java-symbol type="dimen" name="timepicker_text_inset_inner" />
+ <java-symbol type="dimen" name="timepicker_text_size_normal" />
+ <java-symbol type="dimen" name="timepicker_text_size_inner" />
<java-symbol type="string" name="battery_saver_description" />
<java-symbol type="string" name="downtime_condition_summary" />
<java-symbol type="string" name="downtime_condition_line_one" />
@@ -2161,4 +2153,14 @@
<java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
<java-symbol type="string" name="usb_midi_peripheral_model_name" />
+
+ <java-symbol type="bool" name="allow_stacked_button_bar" />
+ <java-symbol type="id" name="spacer" />
+
+ <java-symbol type="xml" name="bookmarks" />
+
+ <java-symbol type="integer" name="config_defaultNightMode" />
+
+ <java-symbol type="integer" name="config_screen_magnification_multi_tap_adjustment" />
+ <java-symbol type="dimen" name="config_screen_magnification_scaling_threshold" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 2b8ed5f..0107356 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -64,8 +64,8 @@
<item name="textColorTertiaryInverse">@color/secondary_text_material_light</item>
<item name="textColorHint">@color/hint_foreground_material_dark</item>
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
- <item name="textColorHighlight">@color/highlighted_text_material_dark</item>
- <item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
+ <item name="textColorHighlight">@color/highlighted_text_material</item>
+ <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorLink">@color/link_text_material_dark</item>
<item name="textColorLinkInverse">@color/link_text_material_light</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
@@ -128,8 +128,8 @@
<item name="listChoiceIndicatorSingle">@drawable/btn_radio_material_anim</item>
<item name="listChoiceIndicatorMultiple">@drawable/btn_check_material_anim</item>
- <item name="listChoiceBackgroundIndicator">?attr/selectableItemBackground</item>
- <item name="activatedBackgroundIndicator">@drawable/activated_background_material</item>
+ <item name="listChoiceBackgroundIndicator">@drawable/list_highlight_material</item>
+ <item name="activatedBackgroundIndicator">@null</item>
<item name="listDividerAlertDialog">@null</item>
@@ -327,7 +327,7 @@
<item name="actionBarWidgetTheme">@null</item>
<item name="actionBarPopupTheme">?attr/popupTheme</item>
<item name="actionBarTheme">@style/ThemeOverlay.Material.ActionBar</item>
- <item name="actionBarItemBackground">?attr/selectableItemBackgroundBorderless</item>
+ <item name="actionBarItemBackground">@drawable/action_bar_item_background_material</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_material</item>
<item name="actionModeCopyDrawable">@drawable/ic_menu_copy_material</item>
@@ -418,8 +418,8 @@
<item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_material_dark</item>
<item name="textColorHint">@color/hint_foreground_material_light</item>
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
- <item name="textColorHighlight">@color/highlighted_text_material_light</item>
- <item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
+ <item name="textColorHighlight">@color/highlighted_text_material</item>
+ <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorLink">@color/link_text_material_light</item>
<item name="textColorLinkInverse">@color/link_text_material_dark</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
@@ -681,7 +681,7 @@
<item name="actionModePopupWindowStyle">@style/Widget.Material.Light.PopupWindow.ActionMode</item>
<item name="actionBarWidgetTheme">@null</item>
<item name="actionBarTheme">@style/ThemeOverlay.Material.ActionBar</item>
- <item name="actionBarItemBackground">?attr/selectableItemBackgroundBorderless</item>
+ <item name="actionBarItemBackground">@drawable/action_bar_item_background_material</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_material</item>
<item name="actionModeCopyDrawable">@drawable/ic_menu_copy_material</item>
@@ -754,6 +754,13 @@
<item name="colorPrimary">@color/primary_material_dark</item>
</style>
+ <!-- Variant of the material (light) theme that has a light status bar background with dark
+ status bar contents. -->
+ <style name="Theme.Material.Light.LightStatusBar">
+ <item name="colorPrimaryDark">@color/primary_dark_material_light_light_status_bar</item>
+ <item name="windowHasLightStatusBar">true</item>
+ </style>
+
<style name="ThemeOverlay" />
<style name="ThemeOverlay.Material" />
@@ -777,8 +784,8 @@
<item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_material_dark</item>
<item name="textColorHint">@color/hint_foreground_material_light</item>
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
- <item name="textColorHighlight">@color/highlighted_text_material_light</item>
- <item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
+ <item name="textColorHighlight">@color/highlighted_text_material</item>
+ <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorLink">@color/link_text_material_light</item>
<item name="textColorLinkInverse">@color/link_text_material_dark</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
@@ -812,8 +819,8 @@
<item name="textColorTertiaryInverse">@color/secondary_text_material_light</item>
<item name="textColorHint">@color/hint_foreground_material_dark</item>
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
- <item name="textColorHighlight">@color/highlighted_text_material_dark</item>
- <item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
+ <item name="textColorHighlight">@color/highlighted_text_material</item>
+ <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
<item name="textColorLink">@color/link_text_material_dark</item>
<item name="textColorLinkInverse">@color/link_text_material_light</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
@@ -972,8 +979,12 @@
{@link android.service.voice.VoiceInteractionSession} class.
this inherits from Theme.Panel, but sets up appropriate animations
and a few custom attributes. -->
- <style name="Theme.Material.VoiceInteractionSession" parent="Theme.Material.Light.Panel">
- <item name="windowAnimationStyle">@style/Animation.VoiceInteractionSession</item>
+ <style name="Theme.Material.VoiceInteractionSession"
+ parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
+ <item name="windowBackground">@color/transparent</item>
+ <item name="colorBackgroundCacheHint">@null</item>
+ <item name="windowIsTranslucent">true</item>
+ <item name="windowAnimationStyle">@style/Animation</item>
</style>
<!-- Theme for the search input bar. -->
@@ -1238,8 +1249,7 @@
</style>
<!-- Default theme for Settings and activities launched from Settings. -->
- <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings" parent="Theme.Material.DayNight.DarkActionBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1251,8 +1261,7 @@
<item name="panelMenuListTheme">@style/Theme.Material.Settings.CompactMenu</item>
</style>
- <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.DayNight.BaseDialog">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1260,8 +1269,7 @@
<style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
- <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.DayNight.Dialog.BaseAlert">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1269,22 +1277,19 @@
<style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
- <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.DayNight.Dialog.Presentation">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
</style>
- <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.DayNight.SearchBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
</style>
- <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
- <item name="colorBackground">@color/white</item>
+ <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.DayNight.CompactMenu">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
<item name="colorAccent">@color/material_deep_teal_500</item>
diff --git a/core/res/res/values/themes_material_daynight.xml b/core/res/res/values/themes_material_daynight.xml
new file mode 100644
index 0000000..5d9b860
--- /dev/null
+++ b/core/res/res/values/themes_material_daynight.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see themes_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+<resources>
+
+ <!-- Material theme (day/night vesion) for activities. -->
+ <style name="Theme.Material.DayNight" parent="Theme.Material.Light" />
+
+ <!-- Variant of Material.DayNight that has a solid (opaque) action bar
+ with an inverse color profile. The dark action bar sharply stands out against
+ the light content (when applicable). -->
+ <style name="Theme.Material.DayNight.DarkActionBar" parent="Theme.Material.Light.DarkActionBar" />
+
+ <!-- Variant of Material.DayNight with no action bar. -->
+ <style name="Theme.Material.DayNight.NoActionBar" parent="Theme.Material.Light.NoActionBar" />
+
+ <!-- Variant of Material.DayNight that has no title bar and fills
+ the entire screen. This theme
+ sets {@link android.R.attr#windowFullscreen} to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen" />
+
+ <!-- Variant of Material.DayNight that has no title bar and fills
+ the entire screen and extends into the display overscan region. This theme
+ sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
+ to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan" />
+
+ <!-- Variant of Material.DayNight that has no title bar and translucent
+ system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
+ {@link android.R.attr#windowTranslucentNavigation} to true. -->
+ <style name="Theme.Material.DayNight.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor" />
+
+ <!-- Default Material.DayNight theme for panel windows. This removes all extraneous
+ window decorations, so you basically have an empty rectangle in which
+ to place your content. It makes the window floating, with a transparent
+ background, and turns off dimming behind the window. -->
+ <style name="Theme.Material.DayNight.Panel" parent="Theme.Material.Light.Panel" />
+
+ <!-- Material theme (day/night vesion) for dialog windows and activities,
+ which is used by the {@link android.app.Dialog} class. This changes
+ the window to be floating (not fill the entire screen), and puts a
+ frame around its contents. You can set this theme on an activity if
+ you would like to make an activity that looks like a Dialog. -->
+ <style name="Theme.Material.DayNight.Dialog" parent="Theme.Material.DayNight.BaseDialog" />
+ <style name="Theme.Material.DayNight.BaseDialog" parent="Theme.Material.Light.BaseDialog" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that has a nice minimum width for
+ a regular dialog. -->
+ <style name="Theme.Material.DayNight.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that does not include a title bar. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a nice minimum width for
+ a regular dialog. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog that has a fixed size. -->
+ <style name="Theme.Material.DayNight.Dialog.FixedSize" parent="Theme.Material.Light.Dialog.FixedSize" />
+
+ <!-- Variant of Theme.Material.DayNight.Dialog.NoActionBar that has a fixed size. -->
+ <style name="Theme.Material.DayNight.Dialog.NoActionBar.FixedSize" parent="Theme.Material.Light.Dialog.NoActionBar.FixedSize" />
+
+ <!-- Theme for a window that will be displayed either full-screen on
+ smaller screens (small, normal) or as a dialog on larger screens
+ (large, xlarge). -->
+ <style name="Theme.Material.DayNight.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge" />
+
+ <!-- Theme for a window without an action bar that will be displayed either full-screen
+ on smaller screens (small, normal) or as a dialog on larger screens
+ (large, xlarge). -->
+ <style name="Theme.Material.DayNight.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar" />
+
+ <!-- Theme for a presentation window on a secondary display. -->
+ <style name="Theme.Material.DayNight.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation" />
+
+ <!-- Material user theme for alert dialog windows, which is used by the
+ {@link android.app.AlertDialog} class. -->
+ <style name="Theme.Material.DayNight.Dialog.Alert" parent="Theme.Material.DayNight.Dialog.BaseAlert" />
+ <style name="Theme.Material.DayNight.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert" />
+
+ <style name="Theme.Material.DayNight.SearchBar" parent="Theme.Material.Light.SearchBar" />
+ <style name="Theme.Material.DayNight.CompactMenu" parent="Theme.Material.Light.CompactMenu" />
+
+</resources>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 1ebc708..e730dff 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -24,9 +24,6 @@
<item name="windowBackground">@color/black</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <!-- We need the windows to be translucent for SwipeToDismiss layout
- to work properly. -->
- <item name="windowIsTranslucent">true</item>
<item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
@@ -42,9 +39,6 @@
<item name="windowBackground">@color/white</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <!-- We need the windows to be translucent for SwipeToDismiss layout
- to work properly. -->
- <item name="windowIsTranslucent">true</item>
<item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
diff --git a/core/res/res/xml/bookmarks.xml b/core/res/res/xml/bookmarks.xml
new file mode 100644
index 0000000..454f456
--- /dev/null
+++ b/core/res/res/xml/bookmarks.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+
+<!--
+ Default system bookmarks for AOSP.
+ Bookmarks for vendor apps should be added to a bookmarks resource overlay; not here.
+
+ Typical shortcuts (not necessarily defined here):
+ 'a': Calculator
+ 'b': Browser
+ 'c': Contacts
+ 'e': Email
+ 'g': GMail
+ 'l': Calendar
+ 'm': Maps
+ 'p': Music
+ 's': SMS
+ 't': Talk
+ 'y': YouTube
+-->
+<bookmarks>
+ <bookmark
+ category="android.intent.category.APP_CALCULATOR"
+ shortcut="a" />
+ <bookmark
+ category="android.intent.category.APP_BROWSER"
+ shortcut="b" />
+ <bookmark
+ category="android.intent.category.APP_CONTACTS"
+ shortcut="c" />
+ <bookmark
+ category="android.intent.category.APP_EMAIL"
+ shortcut="e" />
+ <bookmark
+ category="android.intent.category.APP_CALENDAR"
+ shortcut="l" />
+ <bookmark
+ category="android.intent.category.APP_MAPS"
+ shortcut="m" />
+ <bookmark
+ category="android.intent.category.APP_MUSIC"
+ shortcut="p" />
+ <bookmark
+ category="android.intent.category.APP_MESSAGING"
+ shortcut="s" />
+</bookmarks>
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk
index 6871efd..cb44721 100644
--- a/core/tests/bandwidthtests/Android.mk
+++ b/core/tests/bandwidthtests/Android.mk
@@ -22,9 +22,9 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
LOCAL_PACKAGE_NAME := BandwidthTests
include $(BUILD_PACKAGE)
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/bandwidthtests/AndroidManifest.xml b/core/tests/bandwidthtests/AndroidManifest.xml
index 24221bc..d0a6198 100644
--- a/core/tests/bandwidthtests/AndroidManifest.xml
+++ b/core/tests/bandwidthtests/AndroidManifest.xml
@@ -19,6 +19,7 @@
<application >
<uses-library android:name="android.test.runner" />
+ <uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>
<instrumentation
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 6bdeaf0..79a0b0c 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -24,7 +24,7 @@
LOCAL_DX_FLAGS := --core-library
LOCAL_AAPT_FLAGS = -0 dat -0 gld
LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock mockito-target
-LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common
+LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
LOCAL_PACKAGE_NAME := FrameworksCoreTests
LOCAL_CERTIFICATE := platform
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 226717e..bfaea8f 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -112,6 +112,7 @@
<application android:theme="@style/Theme">
<uses-library android:name="android.test.runner" />
+ <uses-library android:name="org.apache.http.legacy" android:required="false" />
<activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index f9b69a0..32b4557 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -16,7 +16,6 @@
package android.content.pm;
-import android.content.Context;
import android.content.res.Resources;
import android.os.FileUtils;
import android.os.Parcel;
@@ -30,6 +29,7 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -44,6 +44,12 @@
* Tests for {@link android.content.pm.RegisteredServicesCache}
*/
public class RegisteredServicesCacheTest extends AndroidTestCase {
+ private static final int U0 = 0;
+ private static final int U1 = 1;
+ private static final int UID1 = 1;
+ private static final int UID2 = 2;
+ // Represents UID of a system image process
+ private static final int SYSTEM_IMAGE_UID = 20;
private final ResolveInfo r1 = new ResolveInfo();
private final ResolveInfo r2 = new ResolveInfo();
@@ -51,6 +57,7 @@
private final TestServiceType t2 = new TestServiceType("t2", "value2");
private File mDataDir;
private File mSyncDir;
+ private List<UserInfo> mUsers;
@Override
protected void setUp() throws Exception {
@@ -58,97 +65,152 @@
File cacheDir = mContext.getCacheDir();
mDataDir = new File(cacheDir, "testServicesCache");
FileUtils.deleteContents(mDataDir);
- mSyncDir = new File(mDataDir, "system/registered_services");
+ mSyncDir = new File(mDataDir, "system/"+RegisteredServicesCache.REGISTERED_SERVICES_DIR);
mSyncDir.mkdirs();
+ mUsers = new ArrayList<>();
+ mUsers.add(new UserInfo(0, "Owner", UserInfo.FLAG_ADMIN));
+ mUsers.add(new UserInfo(1, "User1", 0));
}
public void testGetAllServicesHappyPath() {
- TestServicesCache cache = new TestServicesCache(mContext, mDataDir);
- cache.addServiceForQuerying(0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null, 1));
- cache.addServiceForQuerying(0, r2, new RegisteredServicesCache.ServiceInfo<>(t2, null, 2));
- assertEquals(2, cache.getAllServicesSize(0));
- assertEquals(2, cache.getPersistentServicesSize(0));
- File file = new File(mSyncDir, TestServicesCache.SERVICE_INTERFACE + ".xml");
- assertTrue("File should be created at " + file, file.length() > 0);
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
+ assertEquals(2, cache.getAllServicesSize(U0));
+ assertEquals(2, cache.getPersistentServicesSize(U0));
+ assertNotEmptyFileCreated(cache, U0);
// Make sure all services can be loaded from xml
- cache = new TestServicesCache(mContext, mDataDir);
- assertEquals(2, cache.getPersistentServicesSize(0));
+ cache = new TestServicesCache();
+ assertEquals(2, cache.getPersistentServicesSize(U0));
}
public void testGetAllServicesReplaceUid() {
- TestServicesCache cache = new TestServicesCache(mContext, mDataDir);
- cache.addServiceForQuerying(0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null, 1));
- cache.addServiceForQuerying(0, r2, new RegisteredServicesCache.ServiceInfo<>(t2, null, 2));
- cache.getAllServices(0);
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
+ cache.getAllServices(U0);
// Invalidate cache and clear update query results
- cache.invalidateCache(0);
+ cache.invalidateCache(U0);
cache.clearServicesForQuerying();
- cache.addServiceForQuerying(0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null, 1));
- cache.addServiceForQuerying(0, r2, new RegisteredServicesCache.ServiceInfo<>(t2, null,
- TestServicesCache.SYSTEM_IMAGE_UID));
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, SYSTEM_IMAGE_UID));
Collection<RegisteredServicesCache.ServiceInfo<TestServiceType>> allServices = cache
- .getAllServices(0);
+ .getAllServices(U0);
assertEquals(2, allServices.size());
Set<Integer> uids = new HashSet<>();
for (RegisteredServicesCache.ServiceInfo<TestServiceType> srv : allServices) {
uids.add(srv.uid);
}
assertTrue("UID must be updated to the new value",
- uids.contains(TestServicesCache.SYSTEM_IMAGE_UID));
- assertFalse("UID must be updated to the new value", uids.contains(2));
+ uids.contains(SYSTEM_IMAGE_UID));
+ assertFalse("UID must be updated to the new value", uids.contains(UID2));
}
public void testGetAllServicesServiceRemoved() {
- TestServicesCache cache = new TestServicesCache(mContext, mDataDir);
- cache.addServiceForQuerying(0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null, 1));
- cache.addServiceForQuerying(0, r2, new RegisteredServicesCache.ServiceInfo<>(t2, null, 2));
- assertEquals(2, cache.getAllServicesSize(0));
- assertEquals(2, cache.getPersistentServicesSize(0));
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
+ assertEquals(2, cache.getAllServicesSize(U0));
+ assertEquals(2, cache.getPersistentServicesSize(U0));
// Re-read data from disk and verify services were saved
- cache = new TestServicesCache(mContext, mDataDir);
- assertEquals(2, cache.getPersistentServicesSize(0));
+ cache = new TestServicesCache();
+ assertEquals(2, cache.getPersistentServicesSize(U0));
// Now register only one service and verify that another one is removed
- cache.addServiceForQuerying(0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null, 1));
- assertEquals(1, cache.getAllServicesSize(0));
- assertEquals(1, cache.getPersistentServicesSize(0));
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ assertEquals(1, cache.getAllServicesSize(U0));
+ assertEquals(1, cache.getPersistentServicesSize(U0));
}
public void testGetAllServicesMultiUser() {
- TestServicesCache cache = new TestServicesCache(mContext, mDataDir);
- int u0 = 0;
- int u1 = 1;
- int pid1 = 1;
- cache.addServiceForQuerying(u0, r1, new RegisteredServicesCache.ServiceInfo<>(t1, null,
- pid1));
- int u1uid = UserHandle.getUid(u1, 0);
- cache.addServiceForQuerying(u1, r2, new RegisteredServicesCache.ServiceInfo<>(t2, null,
- u1uid));
- assertEquals(u1, cache.getAllServicesSize(u0));
- assertEquals(u1, cache.getPersistentServicesSize(u0));
- assertEquals(u1, cache.getAllServicesSize(u1));
- assertEquals(u1, cache.getPersistentServicesSize(u1));
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ int u1uid = UserHandle.getUid(U1, 0);
+ cache.addServiceForQuerying(U1, r2, newServiceInfo(t2, u1uid));
+ assertEquals(1, cache.getAllServicesSize(U0));
+ assertEquals(1, cache.getPersistentServicesSize(U0));
+ assertEquals(1, cache.getAllServicesSize(U1));
+ assertEquals(1, cache.getPersistentServicesSize(U1));
assertEquals("No services should be available for user 3", 0, cache.getAllServicesSize(3));
// Re-read data from disk and verify services were saved
- cache = new TestServicesCache(mContext, mDataDir);
- assertEquals(u1, cache.getPersistentServicesSize(u0));
- assertEquals(u1, cache.getPersistentServicesSize(u1));
+ cache = new TestServicesCache();
+ assertEquals(1, cache.getPersistentServicesSize(U0));
+ assertEquals(1, cache.getPersistentServicesSize(U1));
+ assertNotEmptyFileCreated(cache, U0);
+ assertNotEmptyFileCreated(cache, U1);
+ }
+
+ public void testOnRemove() {
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ int u1uid = UserHandle.getUid(U1, 0);
+ cache.addServiceForQuerying(U1, r2, newServiceInfo(t2, u1uid));
+ assertEquals(1, cache.getAllServicesSize(U0));
+ assertEquals(1, cache.getAllServicesSize(U1));
+ // Simulate ACTION_USER_REMOVED
+ cache.onUserRemoved(U1);
+ // Make queryIntentServices(u1) return no results for U1
+ cache.clearServicesForQuerying();
+ assertEquals(1, cache.getAllServicesSize(U0));
+ assertEquals(0, cache.getAllServicesSize(U1));
+ }
+
+ public void testMigration() {
+ // Prepare "old" file for testing
+ String oldFile = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<services>\n"
+ + " <service uid=\"1\" type=\"type1\" value=\"value1\" />\n"
+ + " <service uid=\"100002\" type=\"type2\" value=\"value2\" />\n"
+ + "<services>\n";
+
+ File file = new File(mSyncDir, TestServicesCache.SERVICE_INTERFACE + ".xml");
+ FileUtils.copyToFile(new ByteArrayInputStream(oldFile.getBytes()), file);
+
+ int u0 = 0;
+ int u1 = 1;
+ TestServicesCache cache = new TestServicesCache();
+ assertEquals(1, cache.getPersistentServicesSize(u0));
+ assertEquals(1, cache.getPersistentServicesSize(u1));
+ assertNotEmptyFileCreated(cache, u0);
+ assertNotEmptyFileCreated(cache, u1);
+ // Check that marker was created
+ File markerFile = new File(mSyncDir, TestServicesCache.SERVICE_INTERFACE + ".xml.migrated");
+ assertTrue("Marker file should be created at " + markerFile, markerFile.exists());
+ // Now introduce 2 service types for u0: t1, t2. type1 will be removed
+ cache.addServiceForQuerying(0, r1, newServiceInfo(t1, 1));
+ cache.addServiceForQuerying(0, r2, newServiceInfo(t2, 2));
+ assertEquals(2, cache.getAllServicesSize(u0));
+ assertEquals(0, cache.getAllServicesSize(u1));
+ // Re-read data from disk. Verify that services were saved and old file was ignored
+ cache = new TestServicesCache();
+ assertEquals(2, cache.getPersistentServicesSize(u0));
+ assertEquals(0, cache.getPersistentServicesSize(u1));
+ }
+
+ private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
+ TestServiceType type, int uid) {
+ return new RegisteredServicesCache.ServiceInfo<>(type, null, uid);
+ }
+
+ private void assertNotEmptyFileCreated(TestServicesCache cache, int userId) {
+ File dir = new File(cache.getUserSystemDirectory(userId),
+ RegisteredServicesCache.REGISTERED_SERVICES_DIR);
+ File file = new File(dir, TestServicesCache.SERVICE_INTERFACE+".xml");
+ assertTrue("File should be created at " + file, file.length() > 0);
}
/**
* Mock implementation of {@link android.content.pm.RegisteredServicesCache} for testing
*/
- private static class TestServicesCache extends RegisteredServicesCache<TestServiceType> {
+ private class TestServicesCache extends RegisteredServicesCache<TestServiceType> {
static final String SERVICE_INTERFACE = "RegisteredServicesCacheTest";
static final String SERVICE_META_DATA = "RegisteredServicesCacheTest";
static final String ATTRIBUTES_NAME = "test";
- // Represents UID of a system image process
- static final int SYSTEM_IMAGE_UID = 20;
private SparseArray<Map<ResolveInfo, ServiceInfo<TestServiceType>>> mServices
= new SparseArray<>();
- public TestServicesCache(Context context, File dir) {
- super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME,
- new TestSerializer(), dir);
+ public TestServicesCache() {
+ super(RegisteredServicesCacheTest.this.mContext,
+ SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, new TestSerializer());
}
@Override
@@ -164,6 +226,33 @@
return new ArrayList<>(map.keySet());
}
+ @Override
+ protected File getUserSystemDirectory(int userId) {
+ File dir = new File(mDataDir, "users/" + userId);
+ dir.mkdirs();
+ return dir;
+ }
+
+ @Override
+ protected List<UserInfo> getUsers() {
+ return mUsers;
+ }
+
+ @Override
+ protected UserInfo getUser(int userId) {
+ for (UserInfo user : getUsers()) {
+ if (user.id == userId) {
+ return user;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected File getDataDirectory() {
+ return mDataDir;
+ }
+
void addServiceForQuerying(int userId, ResolveInfo resolveInfo,
ServiceInfo<TestServiceType> serviceInfo) {
Map<ResolveInfo, ServiceInfo<TestServiceType>> map = mServices.get(userId);
@@ -204,6 +293,11 @@
}
throw new IllegalArgumentException("Unexpected service " + resolveInfo);
}
+
+ @Override
+ public void onUserRemoved(int userId) {
+ super.onUserRemoved(userId);
+ }
}
static class TestSerializer implements XmlSerializerAndParser<TestServiceType> {
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index 1557918..a50fb54 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -29,8 +29,6 @@
import com.android.internal.inputmethod.InputMethodUtils;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -38,19 +36,33 @@
public class InputMethodTest extends InstrumentationTestCase {
private static final boolean IS_AUX = true;
private static final boolean IS_DEFAULT = true;
- private static final boolean IS_AUTO = true;
+ private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true;
private static final boolean IS_ASCII_CAPABLE = true;
+ private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true;
private static final boolean IS_SYSTEM_READY = true;
- private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null;
+ private static final Locale LOCALE_EN = new Locale("en");
private static final Locale LOCALE_EN_US = new Locale("en", "US");
private static final Locale LOCALE_EN_GB = new Locale("en", "GB");
private static final Locale LOCALE_EN_IN = new Locale("en", "IN");
+ private static final Locale LOCALE_FI = new Locale("fi");
+ private static final Locale LOCALE_FI_FI = new Locale("fi", "FI");
+ private static final Locale LOCALE_FIL = new Locale("fil");
+ private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH");
+ private static final Locale LOCALE_FR = new Locale("fr");
+ private static final Locale LOCALE_FR_CA = new Locale("fr", "CA");
private static final Locale LOCALE_HI = new Locale("hi");
private static final Locale LOCALE_JA_JP = new Locale("ja", "JP");
private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN");
private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW");
+ private static final Locale LOCALE_IN = new Locale("in");
+ private static final Locale LOCALE_ID = new Locale("id");
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
private static final String SUBTYPE_MODE_VOICE = "voice";
+ private static final String SUBTYPE_MODE_ANY = null;
+ private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
+ private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
+ private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
+ "EnabledWhenDefaultIsNotAsciiCapable";
@SmallTest
public void testVoiceImes() throws Exception {
@@ -159,10 +171,415 @@
}
}
+ @SmallTest
+ public void testGetImplicitlyApplicableSubtypesLocked() throws Exception {
+ final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
+ createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 =
+ createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+
+ // Make sure that an automatic subtype (overridesImplicitlyEnabledSubtype:true) is
+ // selected no matter what locale is specified.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoEnGB);
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(autoSubtype); // overridesImplicitlyEnabledSubtype == true
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
+ assertEquals(1, result.size());
+ verifyEquality(autoSubtype, result.get(0));
+ }
+
+ // Make sure that a subtype whose locale is exactly equal to the specified locale is
+ // selected as long as there is no no automatic subtype
+ // (overridesImplicitlyEnabledSubtype:true) in the given list.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS); // locale == "en_US"
+ subtypes.add(nonAutoEnGB);
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+
+ // Make sure that a subtype whose locale is exactly equal to the specified locale is
+ // selected as long as there is no automatic subtype
+ // (overridesImplicitlyEnabledSubtype:true) in the given list.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoEnGB); // locale == "en_GB"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnGB, result.get(0));
+ }
+
+ // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and
+ // any subtype whose locale is exactly equal to the specified locale in the given list,
+ // try to find a subtype whose language is equal to the language part of the given locale.
+ // Here make sure that a subtype (locale: "fr_CA") can be found with locale: "fr".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFrCA); // locale == "fr_CA"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFrCA, result.get(0));
+ }
+ // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFr); // locale == "fr"
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoFil);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFrCA, result.get(0));
+ }
+
+ // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its
+ // extra value is selected if and only if all other selected IMEs are not AsciiCapable.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoJa); // not ASCII capable
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi);
+ assertEquals(3, result.size());
+ verifyEquality(nonAutoJa, result.get(0));
+ verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1));
+ verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
+ }
+
+ // Make sure that 3-letter language code can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoFil, result.get(0));
+ }
+
+ // Make sure that we never end up matching "fi" (finnish) with "fil" (filipino).
+ // Also make sure that the first subtype will be used as the last-resort candidate.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoJa);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoJa, result.get(0));
+ }
+
+ // Make sure that "in" and "id" conversion is taken into account.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoIn, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoIn, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoId, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoId, result.get(0));
+ }
+ }
+
+ @SmallTest
+ public void testContainsSubtypeOf() throws Exception {
+ final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+
+ final boolean CHECK_COUNTRY = true;
+
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_VOICE));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_VOICE));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY,
+ SUBTYPE_MODE_ANY));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY,
+ SUBTYPE_MODE_ANY));
+
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that 3-letter language code ("fil") can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFil);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that 3-letter language code ("fil_PH") can be handled.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoFilPH);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that a subtype whose locale is "in" can be queried with "id".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoIn);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+
+ // Make sure that a subtype whose locale is "id" can be queried with "in".
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes.add(nonAutoId);
+ subtypes.add(nonAutoEnUS);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
+ SUBTYPE_MODE_KEYBOARD));
+ }
+ }
+
+ private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale(
+ final Locale locale, final InputMethodInfo imi) {
+ final Context context = getInstrumentation().getTargetContext();
+ final Locale initialLocale = context.getResources().getConfiguration().locale;
+ try {
+ context.getResources().getConfiguration().setLocale(locale);
+ return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(),
+ imi);
+ } finally {
+ context.getResources().getConfiguration().setLocale(initialLocale);
+ }
+ }
+
private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes,
final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) {
final Context context = getInstrumentation().getTargetContext();
- final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesUnderWithLocale(
+ final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale(
context, isSystemReady, preinstalledImes, systemLocale));
assertEquals(expectedImeNames.length, actualImeNames.length);
for (int i = 0; i < expectedImeNames.length; ++i) {
@@ -184,7 +601,7 @@
}
}
- private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesUnderWithLocale(
+ private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale(
final Context context, final boolean isSystemReady,
final ArrayList<InputMethodInfo> imis, final Locale locale) {
final Locale initialLocale = context.getResources().getConfiguration().locale;
@@ -210,11 +627,15 @@
for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) {
final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex);
final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex);
- assertEquals(expectedSubtype, actualSubtype);
- assertEquals(expectedSubtype.hashCode(), actualSubtype.hashCode());
+ verifyEquality(expectedSubtype, actualSubtype);
}
}
+ private static void verifyEquality(InputMethodSubtype expected, InputMethodSubtype actual) {
+ assertEquals(expected, actual);
+ assertEquals(expected.hashCode(), actual.hashCode());
+ }
+
private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
CharSequence label, boolean isAuxIme, boolean isDefault,
List<InputMethodSubtype> subtypes) {
@@ -236,13 +657,27 @@
private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
- boolean isAsciiCapable) {
+ boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
+
+ final StringBuilder subtypeExtraValue = new StringBuilder();
+ if (isEnabledWhenDefaultIsNotAsciiCapable) {
+ subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
+ subtypeExtraValue.append(EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ }
+
+ // TODO: Remove following code. InputMethodSubtype#isAsciiCapable() has been publicly
+ // available since API level 19 (KitKat). We no longer need to rely on extra value.
+ if (isAsciiCapable) {
+ subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
+ subtypeExtraValue.append(EXTRA_VALUE_ASCII_CAPABLE);
+ }
+
return new InputMethodSubtypeBuilder()
.setSubtypeNameResId(0)
.setSubtypeIconResId(0)
.setSubtypeLocale(locale)
.setSubtypeMode(mode)
- .setSubtypeExtraValue("")
+ .setSubtypeExtraValue(subtypeExtraValue.toString())
.setIsAuxiliary(isAuxiliary)
.setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype)
.setIsAsciiCapable(isAsciiCapable)
@@ -253,10 +688,12 @@
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme",
"dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes));
}
@@ -268,33 +705,39 @@
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0",
"dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO,
- !IS_ASCII_CAPABLE));
+ subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1",
"dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2",
"dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme",
"dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes));
}
@@ -321,7 +764,8 @@
final boolean isDefaultIme = false;
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX,
- IS_AUTO, !IS_ASCII_CAPABLE));
+ IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice",
"com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme,
subtypes));
@@ -332,9 +776,11 @@
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
// TODO: This subtype should be marked as IS_ASCII_CAPABLE
subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi",
"com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -345,7 +791,8 @@
final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin",
"com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -356,7 +803,8 @@
final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean",
"com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -368,13 +816,17 @@
new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin",
"com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme,
subtypes));
@@ -385,9 +837,11 @@
final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
- !IS_AUTO, !IS_ASCII_CAPABLE));
+ !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+ !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese",
"com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX,
isDefaultIme, subtypes));
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 95c6867..6659769 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -153,7 +153,6 @@
<library name="org.apache.http.legacy"
file="/system/framework/org.apache.http.legacy.jar" />
-
<!-- These are the standard packages that are white-listed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
<allow-in-power-save package="com.android.providers.downloads" />
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index f94fe66..42b5d5d 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -335,11 +335,6 @@
</family>
<family>
<fileset>
- <file>NotoSansTaiLe-Regular.ttf</file>
- </fileset>
- </family>
- <family>
- <fileset>
<file>NotoSansTaiTham-Regular.ttf</file>
</fileset>
</family>
@@ -408,10 +403,13 @@
<file lang="ja">MTLmr3m.ttf</file>
</fileset>
</family>
- <!-- Note: complex scripts (i.e. those requiring shaping in Harfbuzz) have
- a cumulative limit of 64k glyphs. Thus, if they are placed after the
- large fonts such as DroidSansFallback, they are likely to render
- incorrectly. Please use caution when putting fonts toward the end of
- the list.
+ <!--
+ Noto Sans Tai Le is intentionally kept last, to make sure it doesn't override
+ the East Asian punctuation for Chinese.
-->
+ <family>
+ <fileset>
+ <file>NotoSansTaiLe-Regular.ttf</file>
+ </fileset>
+ </family>
</familyset>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 02bf877..37527e9 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -288,9 +288,6 @@
<font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
</family>
<family>
- <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
- </family>
- <family>
<font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
</family>
<family>
@@ -332,4 +329,11 @@
<family lang="ja">
<font weight="400" style="normal">MTLmr3m.ttf</font>
</family>
+ <!--
+ Noto Sans Tai Le is intentionally kept last, to make sure it doesn't override
+ the East Asian punctuation for Chinese.
+ -->
+ <family>
+ <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
+ </family>
</familyset>
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 1e32d43..94e6469 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -396,4 +396,8 @@
to: /distribute/googleplay/edu/index.html
- from: /preview/google-play-services-wear.html
- to: /training/building-wearables.html
\ No newline at end of file
+ to: /training/building-wearables.html
+
+# ---------- DISTRIBUTE ------------------
+- from /distribute/tools/promote/badge-files.html
+ to: /distribute/tools/promote/badges.html
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index d212b06..75f541a 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -516,23 +516,41 @@
<em>finished_asset</em>.png
drawable-xxhdpi/...
<em>finished_asset</em>.png
+
+ mipmap-ldpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-mdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-hdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxxhdpi/...
+ <em>finished_launcher_asset</em>.png
</pre>
<p>For more information about how to save resources in the application project,
see <a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a>.
</p>
+<p> For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
<h3 id="xxxhdpi-launcher">Provide an xxx-high-density launcher icon</h3>
-<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
+<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
launcher icon image is already extra-extra-high density, the scaling process will make it appear
-less crisp. So you should provide a higher density launcher icon in the <code>drawable-xxxhdpi
+less crisp. So you should provide a higher density launcher icon in the <code>mipmap-xxxhdpi
</code> directory, which the system uses instead of scaling up a smaller version of the icon.</p>
-<p class="note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code> qualifier is necessary only
-to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to
-provide xxxhdpi assets for all your app's images.</p>
+<p class="note"><strong>Note:</strong> The <code>mipmap-xxxhdpi</code> qualifier is necessary
+only to provide a launcher icon that can appear larger than usual on an xxhdpi device. It is best
+practice to place all your launcher icons in the <code>res/mipmap-[density]/</code> folders. This
+enables your app to display launcher icons that have a higher density than the device, without
+scaling up a lower density version of the icon. You do not need to provide xxxhdpi assets for all
+your app's images.</p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for
more information.</p>
diff --git a/docs/html/distribute/tools/promote/badge-files.jd b/docs/html/distribute/tools/promote/badge-files.jd
deleted file mode 100644
index e65e698..0000000
--- a/docs/html/distribute/tools/promote/badge-files.jd
+++ /dev/null
@@ -1,289 +0,0 @@
-page.title=Google Play Badge Files
-page.image=/images/gp-badges-set.png
-page.metaDescription=Download hi-res assets for localized Google Play badges.
-page.tags="badge, google play"
-
-@jd:body
-
-<style>
-table tr td {border:0}
-</style>
-
-<p>The following links provide the Adobe® Illustrator® (.ai) file for the
-two Google Play badges.</p>
-
-
-<img src="{@docRoot}images/brand/en_generic_rgb_wo_60.png" alt="Get It On Google Play">
-
-<div style="clear:left"> </div>
-
-<div class="col-4" style="margin-left:0">
-
- <a href="{@docRoot}downloads/brand/v2/english_get.ai">English (English)</a><br/>
-
- <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/amharic_get.ai">ኣማርኛ (Amharic)</a><br/>
-
-<!--
- <a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
--->
- <a href="{@docRoot}downloads/brand/v2/belarusian_get.ai">Беларуская (Belarusian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/bulgarian_get.ai">български (Bulgarian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/catalan_get.ai">Català (Catalan)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/traditional_chinese_get.ai">中文 (中国) (Chinese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_get.ai">中文(香港) (Chinese Hong Kong)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_get.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/croatian_get.ai">Hrvatski (Croatian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/czech_get.ai">Česky (Czech)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/danish_get.ai">Dansk (Danish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/dutch_get.ai">Nederlands (Dutch)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/estonian_get.ai">Eesti keel (Estonian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/farsi_get.ai">فارسی (Farsi Persian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/filipino_get.ai">Tagalog (Filipino)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/finnish_get.ai">Suomi (Finnish)</a><br/>
-
-</div>
-
-<div class="col-4">
-
- <a href="{@docRoot}downloads/brand/v2/french_get.ai">Français (French)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/german_get.ai">Deutsch (German)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/greek_get.ai">Ελληνικά (Greek)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hebrew_get.ai">עברית (Hebrew)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hindi_get.ai">हिन्दी (Hindi)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hungarian_get.ai">Magyar (Hungarian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/indonesian_get.ai">Bahasa Indonesia (Indonesian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/italian_get.ai">Italiano (Italian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/japanese_get.ai">日本語 (Japanese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/kazakh_get.ai">Қазақ тілі (Kazakh)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/korean_get.ai">한국어 (Korean)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/latvian_get.ai">Latviski (Latvian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/lithuanian_get.ai">Lietuviškai (Lithuanian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/malay_get.ai">Bahasa Melayu (Malay)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/norwegian_get.ai">Norsk (Norwegian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/polish_get.ai">Polski (Polish)</a><br/>
-
-</div>
-
-<div class="col-4" style="margin-right:0">
-
- <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_get.ai">Português (Portuguese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_get.ai">Português Brasil (Portuguese Brazil)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/romanian_get.ai">Românã (Romanian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/russian_get.ai">Pусский (Russian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/serbian_get.ai">Српски / srpski (Serbian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/slovak_get.ai">Slovenčina (Slovak)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/slovenian_get.ai">Slovenščina (Slovenian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/spanish_get.ai">Español (Spanish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/spanish_latam_get.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/swahili_get.ai">Kiswahili (Swahili)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/swedish_get.ai">Svenska (Swedish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/thai_get.ai">ภาษาไทย (Thai)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/turkish_get.ai">Türkçe (Turkish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/uk_generic_rgb_wo.ai">Українська (Ukrainian)</a><br/>
- <a href="{@docRoot}downloads/brand/vi_generic_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/zulu_get.ai">isiZulu (Zulu)</a><br/>
-
-</div>
-<div style="clear:left"> </div>
-
-
-
-
-
-
-
-
-
-
-<img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="Android App On Google Play">
-
-<div style="clear:left"> </div>
-
-<div class="col-4" style="margin-left:0">
-
- <a href="{@docRoot}downloads/brand/v2/english_app.ai">English (English)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/afrikaans_app.ai">Afrikaans (Afrikaans)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/amharic_app.ai">ኣማርኛ (Amharic)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/arabic_app.ai">العربية (Arabic)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/belarusian_app.ai">Беларуская (Belarusian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/bulgarian_app.ai">български (Bulgarian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/catalan_app.ai">Català (Catalan)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/traditional_chinese_app.ai">中文 (中国) (Chinese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_app.ai">中文(香港) (Chinese Hong Kong)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_app.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/croatian_app.ai">Hrvatski (Croatian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/czech_app.ai">Česky (Czech)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/danish_app.ai">Dansk (Danish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/dutch_app.ai">Nederlands (Dutch)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/estonian_app.ai">Eesti keel (Estonian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/farsi_app.ai">فارسی (Farsi Persian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/filipino_app.ai">Tagalog (Filipino)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/finnish_app.ai">Suomi (Finnish)</a><br/>
-
-</div>
-
-<div class="col-4">
-
- <a href="{@docRoot}downloads/brand/v2/french_app.ai">Français (French)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/german_app.ai">Deutsch (German)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/greek_app.ai">Ελληνικά (Greek)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hebrew_app.ai">עברית (Hebrew)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hindi_app.ai">हिन्दी (Hindi)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/hungarian_app.ai">Magyar (Hungarian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/indonesian_app.ai">Bahasa Indonesia (Indonesian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/italian_app.ai">Italiano (Italian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/japanese_app.ai">日本語 (Japanese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/korean_app.ai">한국어 (Korean)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/latvian_app.ai">Latviski (Latvian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/lithuanian_app.ai">Lietuviškai (Lithuanian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/malay_app.ai">Bahasa Melayu (Malay)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/norwegian_app.ai">Norsk (Norwegian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/polish_app.ai">Polski (Polish)</a><br/>
-
-
-</div>
-
-<div class="col-4" style="margin-right:0">
-
- <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_app.ai">Português (Portuguese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_app.ai">Português Brasil (Portuguese Brazil)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/romanian_app.ai">Românã (Romanian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/russian_app.ai">Pусский (Russian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/serbian_app.ai">Српски / srpski (Serbian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/slovak_app.ai">Slovenčina (Slovak)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/slovenian_app.ai">Slovenščina (Slovenian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/spanish_app.ai">Español (Spanish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/spanish_latam_app.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/swahili_app.ai">Kiswahili (Swahili)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/swedish_app.ai">Svenska (Swedish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/thai_app.ai">ภาษาไทย (Thai)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/turkish_app.ai">Türkçe (Turkish)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/ukranian_app.ai">Українська (Ukrainian)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/vietnamese_app.ai">Tiếng Việt (Vietnamese)</a><br/>
-
- <a href="{@docRoot}downloads/brand/v2/zulu_app.ai">isiZulu (Zulu)</a><br/>
-
-</div>
-<div style="clear:left"> </div>
-
-
-
-
-
-
-<h2>Guidelines</h2>
-
- <ul>
- <li>Do not modify the color, proportions, spacing or any other aspect of the badge image.
- </li>
- <li>When used alongside logos for other application marketplaces, the Google Play logo
- should be of equal or greater size.</li>
- <li>When used online, the badge should link to either:
- <ul>
- <li>A list of products published by you, for example:<br />
- <span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
- </li>
- <li>A specific app product details page within Google Play, for example:<br />
- <span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
- </li>
- </ul>
- </li>
- </ul>
-
-<p>For more information, see the
-<a href="{@docRoot}distribute/tools/promote/brand.html#brand-google_play">Brand
-Guidelines</a>.
-
-
-<p>To quickly create a badge that links to your apps on Google Play,
-use the <a
-href="{@docRoot}distribute/tools/promote/badges.html">Googe Play badge generator</a>.</p>
diff --git a/docs/html/distribute/tools/promote/brand.jd b/docs/html/distribute/tools/promote/brand.jd
index 22441df..a12e753 100644
--- a/docs/html/distribute/tools/promote/brand.jd
+++ b/docs/html/distribute/tools/promote/brand.jd
@@ -5,7 +5,7 @@
@jd:body
-<p>We encourage you to use the Android and Google Play brands with your Android app
+<p>We encourage you to use the Android brand with your Android app
promotional materials. You can use the icons and other assets on this page
provided that you follow the guidelines.</p>
@@ -89,47 +89,9 @@
<p>The custom typeface may not be used.</p>
-<h2 id="brand-google_play">Google Play</h2>
+<p>The following are guidelines for the Google Play brand.</p>
-
- <p>The following are guidelines for the Google Play brand
- and related assets.</p>
-
-<h4>Google Play in text</h4>
-
-<p>Always include a TM symbol on the first or most prominent instance of Google Play™
-in text.</p>
-
-<p>When referring to the mobile experience, use "Google Play" unless the text is clearly
-instructional for the user. For example, a marketing headline might read "Download our
-games on Google Play™," but instructional text would read "Download our games using the Google
-Play™ store app."
-
- <p>Any use of the Google Play name or icon needs to include this
- attribution in your communication:</p>
-
-<blockquote><em>Google Play is a trademark of Google Inc.</em></blockquote>
-
-
- <div style="float:right;width:96px;margin-left:30px;margin-top:-20px">
- <img src="{@docRoot}images/brand/Google_Play_Store_96.png" alt="">
- <p style="text-align:center">
- <a href="{@docRoot}images/brand/Google_Play_Store_48.png">48x48</a> |
- <a href="{@docRoot}images/brand/Google_Play_Store_96.png">96x96</a><br>
- <a href="{@docRoot}images/brand/Google_Play_Store_600.png">600x576</a>
- </p>
- </div>
-
-<h4>Google Play store icon</h4>
-
-<p>You may use the Google Play store icon, but you may not modify it.</p>
-
-<p>As mentioned above, when referring to the Google Play store app in copy, use the full name:
-"Google Play store." However, when labeling the Google Play store icon directly, it's OK to use
-"Play Store" alone to accurately reflect the icon label as it appears on a device.</p>
-
-
-<h4>Google Play badge</h4>
+<h4>Google Play™ Badges</h4>
<div style="float:right;clear:right;width:172px;margin-left:30px">
<img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="">
@@ -145,21 +107,21 @@
<a href="{@docRoot}images/brand/en_generic_rgb_wo_60.png">172x60</a></p>
</div>
- <p>The "Get it on Google Play" and "Android App on Google Play" logos are
- badges that you can use on your website and promotional materials, to point
- to your products on Google Play. Additional Google Play badge formats and
+ <p>Use the "Get it on Google Play" and "Android App on Google Play" badges on your website and
+ promotional materials to point to your products on Google Play. These badges are both available
+ in over 40 languages. Additional Google Play badge formats and
badges for music, books, magazines, movies, and TV shows are also available.
Use the <a
href="https://support.google.com/googleplay/contact/brand_developer">Android
and Google Play Brand Permissions Inquiry form</a> to request
those badges.</p>
+ <p>Google Play badge guidelines:</p>
<ul>
- <li>Don't modify the color, proportions, spacing, or any other aspect of the badge image.
- </li>
- <li>When used alongside logos for other application marketplaces, the Google Play logo
+ <li>Don't modify the color, proportions, spacing, or any other aspect of the badge.</li>
+ <li>When used alongside logos for other application marketplaces, the Google Play badge
should be of equal or greater size.</li>
- <li>When used online, the badge should link to either:
+ <li>When used online, the badge should link to either:</li>
<ul>
<li>A list of products published by you, for example:<br />
<span style="margin-left:1em;">http://play.google.com/store/search?q=<em>publisherName</em></span>
@@ -168,24 +130,62 @@
<span style="margin-left:1em;">http://play.google.com/store/apps/details?id=<em>packageName</em></span>
</li>
</ul>
+ <li>You do not need to include a legal attribution if you are only using a Google Play badge.
+ However, keep in mind that:</li>
+ <ul>
+ <li>If you make any mention of Google Play or Android outside of the badge a legal attribution
+ must be included. </li>
+ <li>If you are including another app store’s legal attribution then include this legal
+ attribution:</li>
+ <ul>
+ <li>Google Play is a trademark of Google Inc.</li>
+ </ul>
</li>
+ <li>Use of the Google Play badge does not need to be reviewed or approved by the Google Play
+ brand team unless the marketing campaign will have over 1 million impressions.</li>
</ul>
<p>To quickly create a badge that links to your apps on Google Play,
use the <a
href="{@docRoot}distribute/tools/promote/badges.html">Google Play badge generator</a>
- (provides the badge in over 40 languages).</p>
-
- <p>To create your own size, download an Adobe® Illustrator® (.ai) file for the
- <a href="{@docRoot}distribute/tools/promote/badge-files.html">Google Play
- badge in over 40 languages</a>.</p>
+ (badges available in over 40 languages).</p>
<p>For details on all the ways that you can link to your product details page in Google Play,
see <a href="{@docRoot}distribute/tools/promote/linking.html">Linking to your products</a>.</p>
+<h2 id="Marketing_Review">Google Play in Text</h2>
+
+<p>Any use of Google Play in text must be reviewed and approved by the Google Play brand team.
+Submit your marketing via the <a href="https://support.google.com/googleplay/contact/brand_developer">
+Android and Google Play Partner Brand Inquiry Form.</a></p>
+
+<p>Always include a ™ symbol on the first or most prominent instance of Google Play™ in text.</p>
+
+<p>When mentioning that a product is available on Google Play always say “on Google Play”</p>
+
+<ul>
+<li><span style="color:red">Incorrect</span>: Our app is now available from Google Play.</li>
+<li><span style="color:green">Correct</span>: Our app is now available on Google Play.</li>
+</ul>
+<br>
+<p>Only refer to Google Play as the Google Play™ store app in instructional text meant to inform a
+customer about how to find or download your product on Google Play.</p>
+
+<ul>
+<li><span style="color:red">Incorrect</span>: Download our games using the Google Play™ store app.</li>
+<li><span style="color:green">Correct</span>: This is how you download our app using the Google
+Play™ store app.</li>
+</ul>
+<br>
+
+<p>Any use of the Google Play name in your marketing or communications needs to be accompanied by
+this legal attribution:</p>
+
+<p><em>Google Play is a trademark of Google Inc.</em></p>
+
<h2 id="Marketing_Review">Marketing Reviews and Brand Inquiries</h2>
<p>Use the <a
href="https://support.google.com/googleplay/contact/brand_developer">Android
and Google Play Brand Permissions Inquiry form</a> to submit any marketing
-reviews or brand inquires. Typical response time is at least one week.</p>
+reviews or brand inquires. Typical response time is at least one week.</p>
\ No newline at end of file
diff --git a/docs/html/distribute/tools/promote/device-art-resources/wear/thumb.png b/docs/html/distribute/tools/promote/device-art-resources/wear/thumb.png
new file mode 100644
index 0000000..adfe16f
--- /dev/null
+++ b/docs/html/distribute/tools/promote/device-art-resources/wear/thumb.png
Binary files differ
diff --git a/docs/html/distribute/tools/promote/device-art-resources/wear_round/port_back.png b/docs/html/distribute/tools/promote/device-art-resources/wear_round/port_back.png
new file mode 100644
index 0000000..0b3d04a
--- /dev/null
+++ b/docs/html/distribute/tools/promote/device-art-resources/wear_round/port_back.png
Binary files differ
diff --git a/docs/html/distribute/tools/promote/device-art-resources/wear_square/port_back.png b/docs/html/distribute/tools/promote/device-art-resources/wear_square/port_back.png
new file mode 100644
index 0000000..aa44795
--- /dev/null
+++ b/docs/html/distribute/tools/promote/device-art-resources/wear_square/port_back.png
Binary files differ
diff --git a/docs/html/distribute/tools/promote/device-art.jd b/docs/html/distribute/tools/promote/device-art.jd
index 3902b30..814177b 100644
--- a/docs/html/distribute/tools/promote/device-art.jd
+++ b/docs/html/distribute/tools/promote/device-art.jd
@@ -1,13 +1,13 @@
page.title=Device Art Generator
page.image=/images/device-art-ex-crop.jpg
-page.metaDescription=Drag and drop screenshots of your app into real device artwork, for better looking promotional images and improved visual context.
+page.metaDescription=Drag and drop screenshots of your app into device artwork, for better looking promotional images and improved visual context.
meta.tags="disttools, promoting, deviceart, marketing"
page.tags="device, deviceart, nexus, assets"
Xnonavpage=true
@jd:body
-<p>The device art generator enables you to quickly wrap app screenshots in real device artwork. This provides better visual context for your app screenshots on your website or in other promotional materials</p>
+<p>The device art generator enables you to quickly wrap app screenshots in device artwork. This provides better visual context for your app screenshots on your website or in other promotional materials</p>
<p class="note"><strong>Note</strong>: Do <em>not</em> use graphics created here in your 1024x500
feature image or screenshots for your Google Play app listing.</p>
@@ -41,6 +41,12 @@
<label for="output-glare">Screen Glare</label><br><br>
<a class="button" id="rotate-button">Rotate</a>
</p>
+ <p id="wear-customizations">
+ <input type="radio" id="output-square" name="output-wear" checked="checked" class="form-field-checkbutton">
+ <label for="output-square">Square</label><br>
+ <input type="radio" id="output-round" name="output-wear" class="form-field-checkbutton">
+ <label for="output-round">Round</label><br><br>
+ </p>
</div>
<div class="layout-content-col span-10">
<!-- position:relative fixes an issue where dragging an image out of a inline-block container
@@ -52,7 +58,7 @@
</div>
<div class="unsupported-browser" style="display: none">
- <p class="warning"><strong>Error:</strong> This page requires
+ <p class="warning"><strong>Error:</strong> This page requires
<span id="unsupported-browser-reason">certain features</span>, which your web browser
doesn't support. To continue, navigate to this page on a supported web browser, such as
<strong>Google Chrome</strong>.</p>
@@ -165,6 +171,10 @@
// Global constants
var MSG_INVALID_INPUT_IMAGE = 'Invalid screenshot provided. Screenshots must be PNG files '
+ 'matching the target device\'s screen aspect ratio in either portrait or landscape.';
+ var MSG_INVALID_WEAR_IMAGE = 'Invalid screenshot provided. Screenshots must be PNG files '
+ + 'matching the target device\'s screen aspect ratio.'
+ + ' Capture screenshots from a Wear emulator or device with '
+ + '<a href="http://developer.android.com/tools/debugging/debugging-studio.html#screenCap">Android Studio</a>.';
var MSG_NO_INPUT_IMAGE = 'Drag a screenshot (in PNG format) from your desktop onto a '
+ 'target device above.'
var MSG_GENERATING_IMAGE = 'Generating device art…';
@@ -270,6 +280,47 @@
portSize: [768,1280],
archived: true
},
+ {
+ id: 'wear',
+ title: 'Android Wear',
+ url: 'http://www.android.com/wear/',
+ physicalSize: 1.8,
+ physicalHeight: 1.8,
+ density: 'HDPI',
+ landRes: ['back'],
+ landOffset: [225,206],
+ portRes: ['back'],
+ portOffset: [200,214],
+ portSize: [320,320],
+ },
+ {
+ id: 'wear_square',
+ title: 'Android Wear Square',
+ url: 'http://www.android.com/wear/',
+ physicalSize: 1.8,
+ physicalHeight: 1.8,
+ density: 'HDPI',
+ landRes: ['back'],
+ landOffset: [225,206],
+ portRes: ['back'],
+ portOffset: [200,214],
+ portSize: [320,320],
+ hidden: true
+ },
+ {
+ id: 'wear_round',
+ title: 'Android Wear Round',
+ url: 'http://www.android.com/wear/',
+ physicalSize: 1.8,
+ physicalHeight: 1.8,
+ density: 'HDPI',
+ landRes: ['back'],
+ landOffset: [161,167],
+ portRes: ['back'],
+ portOffset: [128,134],
+ portSize: [320,320],
+ hidden: true
+ },
];
DEVICES = DEVICES.sort(function(x, y) { return x.physicalSize - y.physicalSize; });
@@ -343,15 +394,21 @@
$('#output').html(MSG_NO_INPUT_IMAGE);
$('#frame-customizations').hide();
+ $('#wear-customizations').hide();
$('#output-shadow, #output-glare').click(function() {
createFrame();
});
+ $('input[name="output-wear"]').change(function() {
+ createFrame();
+ });
+
// Build device list.
$.each(DEVICES, function() {
var resolution = this.actualResolution || this.portSize;
var scaleFactorText = '';
+ var deviceList = '.device-list.primary';
if (resolution[0] != this.portSize[0]) {
scaleFactorText = '<br>' + (100 * (this.portSize[0] / resolution[0])).toFixed(0) +
'% size output';
@@ -359,6 +416,12 @@
scaleFactorText = '<br> ';
}
+ if (this.archived) {
+ deviceList = '.device-list.archive';
+ } else if (this.hidden) {
+ deviceList = '.device-list.hidden';
+ }
+
$('<li>')
.append($('<div>')
.addClass('thumb-container')
@@ -374,7 +437,7 @@
'<br>' + this.physicalSize + '" @ ' + this.density +
'<br>' + (resolution[0] + 'x' + resolution[1]) + scaleFactorText))
.data('deviceId', this.id)
- .appendTo(this.archived ? '.device-list.archive' : '.device-list.primary');
+ .appendTo(deviceList)
});
// Set up "older devices" expando.
@@ -406,7 +469,11 @@
evt.preventDefault();
loadImageFromFileList(evt.dataTransfer.files, function(data) {
if (data == null) {
- $('#output').html(MSG_INVALID_INPUT_IMAGE);
+ if (g_currentDevice.id == 'wear') {
+ $('#output').html(MSG_INVALID_WEAR_IMAGE);
+ }else {
+ $('#output').html(MSG_INVALID_INPUT_IMAGE);
+ }
return;
}
loadImageFromUri(data.uri, function(img) {
@@ -450,6 +517,14 @@
function createFrame() {
var port;
+ if (g_currentDevice.id == 'wear' || g_currentDevice.id == 'wear_square' || g_currentDevice.id == 'wear_round') {
+ if ($('#output-square').is(':checked')) {
+ g_currentDevice = getDeviceById('wear_square');
+ } else {
+ g_currentDevice = getDeviceById('wear_round');
+ }
+ }
+
var aspect1 = g_currentImage.naturalWidth / g_currentImage.naturalHeight;
var aspect2 = g_currentDevice.portSize[0] / g_currentDevice.portSize[1];
@@ -458,11 +533,18 @@
} else if (aspect1 == 1 / aspect2) {
port = false;
} else {
- alert('The screenshot must have an aspect ratio of ' +
+ if (g_currentDevice.id == 'wear_square' || g_currentDevice.id == 'wear_round') {
+ alert('The screenshot must have an aspect ratio of ' +
+ aspect2.toFixed(3) +
+ ' (ideally ' + g_currentDevice.portSize[0] + 'x' + g_currentDevice.portSize[1] + ').');
+ $('#output').html(MSG_INVALID_WEAR_IMAGE);
+ }else {
+ alert('The screenshot must have an aspect ratio of ' +
aspect2.toFixed(3) + ' or ' + (1 / aspect2).toFixed(3) +
' (ideally ' + g_currentDevice.portSize[0] + 'x' + g_currentDevice.portSize[1] +
' or ' + g_currentDevice.portSize[1] + 'x' + g_currentDevice.portSize[0] + ').');
- $('#output').html(MSG_INVALID_INPUT_IMAGE);
+ $('#output').html(MSG_INVALID_INPUT_IMAGE);
+ }
return;
}
@@ -497,9 +579,37 @@
ctx.drawImage(resourceImages['shadow'], 0, 0);
}
ctx.drawImage(resourceImages['back'], 0, 0);
- ctx.fillStyle = '#000';
- ctx.fillRect(offset[0], offset[1], size[0], size[1]);
- ctx.drawImage(g_currentImage, offset[0], offset[1], size[0], size[1]);
+
+ if (g_currentDevice.id == 'wear_round') {
+ var scratchCanvas = document.createElement('canvas');
+ scratchCanvas.width = width;
+ scratchCanvas.height = height;
+ var scratchCtx = scratchCanvas.getContext('2d');
+
+
+ //drawing code
+ scratchCtx.clearRect(offset[0], offset[1], scratchCanvas.width, scratchCanvas.height);
+
+ scratchCtx.globalCompositeOperation = 'source-over'; //default
+
+ scratchCtx.drawImage(g_currentImage, offset[0], offset[1], size[0], size[1]);
+
+ scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity
+ scratchCtx.globalCompositeOperation = 'destination-in';
+ scratchCtx.beginPath();
+ scratchCtx.arc(288, 294, size[0] / 2, 0, 2 * Math.PI, false);
+ scratchCtx.closePath();
+ scratchCtx.fill();
+
+ // After tinkering with the offset, the 1 in the x-position drew the image
+ // perfectly
+ ctx.drawImage(scratchCanvas, 1, 0);
+ } else {
+ ctx.fillStyle = '#000';
+ ctx.fillRect(offset[0], offset[1], size[0], size[1]);
+ ctx.drawImage(g_currentImage, offset[0], offset[1], size[0], size[1]);
+ }
+
if (resourceImages['fore'] && $('#output-glare').is(':checked')) {
ctx.drawImage(resourceImages['fore'], 0, 0);
}
@@ -546,7 +656,13 @@
.attr('data-downloadurl', ['image/png', filename, imageUrl].join(':')))
.appendTo($('#output').empty());
- $('#frame-customizations').show();
+ if (g_currentDevice.id == 'wear' || g_currentDevice.id == 'wear_round' || g_currentDevice.id == 'wear_square') {
+ $('#wear-customizations').show();
+ $('#frame-customizations').hide();
+ } else {
+ $('#frame-customizations').show();
+ $('#wear-customizations').hide();
+ }
}
}
diff --git a/docs/html/google/gcm/c2dm.jd b/docs/html/google/gcm/c2dm.jd
index fc95c2b..6ae7c1a 100644
--- a/docs/html/google/gcm/c2dm.jd
+++ b/docs/html/google/gcm/c2dm.jd
@@ -75,7 +75,6 @@
<dt><strong>Canonical registration ID</strong></dt>
<dd>There may be situations where the server ends up with 2 registration IDs for the same device. If the GCM response contains a registration ID, simply replace the registration ID you have with the one provided. With this feature your application doesn't need to send the device ID to your server anymore. For more information, see <a href="adv.html#canonical">Advanced Topics</a>.</dd>
</dl>
-<p>GCM also provides client and server <a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a> to make writing your code easier.</p>
<h3 id="interop">Relationship between C2DM and GCM</h3>
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index 052cf75..e3cacf9 100644
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -232,7 +232,7 @@
1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
</pre>
-<p>Google Plays sends a response to your {@link android.app.PendingIntent} to the {@link android.app.Activity#onActivityResult onActivityResult} method of your application. The {@link android.app.Activity#onActivityResult onActivityResult} method will have a result code of {@code Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the types of order information that is returned in the response {@link android.content.Intent}, see <a href="{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app Billing Reference</a>.</p>
+<p>Google Play sends a response to your {@link android.app.PendingIntent} to the {@link android.app.Activity#onActivityResult onActivityResult} method of your application. The {@link android.app.Activity#onActivityResult onActivityResult} method will have a result code of {@code Activity.RESULT_OK} (1) or {@code Activity.RESULT_CANCELED} (0). To see the types of order information that is returned in the response {@link android.content.Intent}, see <a href="{@docRoot}google/play/billing/billing_reference.html#getBuyIntent">In-app Billing Reference</a>.</p>
<p>The purchase data for the order is a String in JSON format that is mapped to the {@code INAPP_PURCHASE_DATA} key in the response {@link android.content.Intent}, for example:
<pre>
@@ -243,11 +243,19 @@
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
- "purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
+ "purchaseToken":<em>"opaque-token-up-to-1000-characters"</em>
}'
</pre>
</p>
+<p class="note"><strong>Note:</strong> Google Play generates a token for the
+purchase. This token is an opaque character sequence that may be up to 1,000
+characters long. Pass this entire token to other methods, such as when you
+consume the purchase, as described in
+<a href="{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
+a Purchase</a>. Do not abbreviate or truncate this token; you must save and
+return the entire token.</p>
+
<p>Continuing from the previous example, you get the response code, purchase data, and signature from the response {@link android.content.Intent}.</p>
<pre>
@Override
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index 902c2c6..da9178d 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -202,7 +202,12 @@
</tr>
<tr>
<td>{@code purchaseToken}</td>
- <td>A token that uniquely identifies a purchase for a given item and user pair. </td>
+ <td>A token that uniquely identifies a purchase for a given item and user
+ pair. This token may be up to 1,000 characters long.
+ Pass this entire token to other methods, such as when you consume the
+ purchase (as described in
+<a href="{@docRoot}training/in-app-billing/purchase-iab-products.html#Consume">Consume
+ a Purchase</a>). Do not abbreviate or truncate this token.</td>
</tr>
</table>
</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 7ebda53..b6f1c49 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -1,5 +1,5 @@
page.title=Supporting Multiple Screens
-page.metaDescription=Nanaging UIs for the best display on multiple screen sizes.
+page.metaDescription=Managing UIs for the best display on multiple screen sizes.
meta.tags="multiple screens"
@jd:body
@@ -348,13 +348,13 @@
<code>hdpi</code> (high), <code>xhdpi</code> extra-high), <code>xxhdpi</code>
(extra-extra-high), and <code>xxxhdpi</code> (extra-extra-extra-high). For example, bitmaps
for high-density screens should go in {@code drawable-hdpi/}.</p>
- <p class="note" id="xxxhdpi-note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code>
+ <p class="note" id="xxxhdpi-note"><strong>Note:</strong> The <code>mipmap-xxxhdpi</code>
qualifier is necessary only to provide a launcher icon that can appear larger than usual on an
xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.</p>
<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest
density launcher icon image is already extra-extra-high-density, the scaling process will make it
appear less crisp. So you should provide a higher density launcher icon in the
-<code>drawable-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
+<code>mipmap-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
version of the icon.</p>
<p>See <a href="{@docRoot}design/style/iconography.html#xxxhdpi-launcher">Provide an
xxx-high-density launcher icon</a> for more information. You should not use the
@@ -362,6 +362,16 @@
</li>
</ul>
+<p class="note"><strong>Note:</strong> Place all your launcher icons in the
+<code>res/mipmap-[density]/</code> folders, rather than the <code>res/drawable-[density]/</code>
+folders. The Android system retains the resources in these density-specific folders, such as
+mipmap-xxxhdpi, regardless of the screen resolution of the device where your app is installed. This
+behavior allows launcher apps to pick the best resolution icon for your app to display on the home
+screen. For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.
+</p>
+
+
<p>The size and density configuration qualifiers correspond to the generalized sizes and densities
described in <a href="#range">Range of screens supported</a>, above.</p>
@@ -538,9 +548,9 @@
sizes and densities, see <a href="#range">Range of Screens Supported</a>, earlier in this
document.</p>
-<p>For example, the following is a list of resource directories in an application that
-provides different layout designs for different screen sizes and different bitmap drawables
-for medium, high, and extra-high-density screens.</p>
+<p>For example, the following application resource directories provide different layout designs
+for different screen sizes and different drawables. Use the <code>mipmap/</code> folders for
+launcher icons.</p>
<pre class="classic">
res/layout/my_layout.xml // layout for normal screen size ("default")
@@ -548,10 +558,16 @@
res/layout-xlarge/my_layout.xml // layout for extra-large screen size
res/layout-xlarge-land/my_layout.xml // layout for extra-large in landscape orientation
-res/drawable-mdpi/my_icon.png // bitmap for medium-density
-res/drawable-hdpi/my_icon.png // bitmap for high-density
-res/drawable-xhdpi/my_icon.png // bitmap for extra-high-density
-res/drawable-xxhdpi/my_icon.png // bitmap for extra-extra-high-density
+res/drawable-mdpi/graphic.png // bitmap for medium-density
+res/drawable-hdpi/graphic.png // bitmap for high-density
+res/drawable-xhdpi/graphic.png // bitmap for extra-high-density
+res/drawable-xxhdpi/graphic.png // bitmap for extra-extra-high-density
+
+res/mipmap-mdpi/my_icon.png // launcher icon for medium-density
+res/mipmap-hdpi/my_icon.png // launcher icon for high-density
+res/mipmap-xhdpi/my_icon.png // launcher icon for extra-high-density
+res/mipmap-xxhdpi/my_icon.png // launcher icon for extra-extra-high-density
+res/mipmap-xxxhdpi/my_icon.png // launcher icon for extra-extra-extra-high-density
</pre>
<p>For more information about how to use alternative resources and a complete list of
@@ -560,7 +576,7 @@
Providing Alternative Resources</a>.</p>
<p>Be aware that, when the Android system picks which resources to use at runtime, it uses
-certain logic to determing the "best matching" resources. That is, the qualifiers you use don't
+certain logic to determine the "best matching" resources. That is, the qualifiers you use don't
have to exactly match the current screen configuration in all cases in order for the system to
use them. Specifically, when selecting resources based on the size qualifiers, the system will
use resources designed for a screen smaller than the current screen if there are no resources
@@ -703,10 +719,10 @@
smallest width your layout supports once it's complete.</p>
<p class="note"><strong>Note:</strong> Remember that all the figures used with these new size APIs
-are density-indpendent pixel (dp) values and your layout dimensions should also always be defined
+are density-independent pixel (dp) values and your layout dimensions should also always be defined
using dp units, because what you care about is the amount of screen space available after the system
accounts for screen density (as opposed to using raw pixel resolution). For more information about
-density-indpendent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
+density-independent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
document.</p>
@@ -728,7 +744,7 @@
a part of your application's window space, although your layout does not declare it, so it reduces
the space available for your layout and you must account for it in your design.</p>
-<p class="table-caption"><strong>Table 2.</strong> New configuration qualifers for screen size
+<p class="table-caption"><strong>Table 2.</strong> New configuration qualifiers for screen size
(introduced in Android 3.2).</p>
<table>
<tr><th>Screen configuration</th><th>Qualifier values</th><th>Description</th></tr>
@@ -745,7 +761,7 @@
use this qualifier to ensure that, regardless of the screen's current orientation, your
application's has at least {@code <N>} dps of width available for its UI.</p>
<p>For example, if your layout requires that its smallest dimension of screen area be at
-least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+least 600 dp at all times, then you can use this qualifier to create the layout resources, {@code
res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
@@ -851,7 +867,7 @@
res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)
</pre>
-<p>Notice that the previous two sets of example resources use the "smallest width" qualifer, {@code
+<p>Notice that the previous two sets of example resources use the "smallest width" qualifier, {@code
sw<N>dp}, which specifies the smallest of the screen's two sides, regardless of the
device's current orientation. Thus, using {@code sw<N>dp} is a simple way to specify the
overall screen size available for your layout by ignoring the screen's orientation.</p>
@@ -1392,4 +1408,4 @@
<p>For more information about creating AVDs from the command line, see <a
href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the
-Command Line</a>.</p>
\ No newline at end of file
+Command Line</a>.</p>
diff --git a/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd
index bed4b4d..45bd76a 100644
--- a/docs/html/guide/topics/admin/device-admin.jd
+++ b/docs/html/guide/topics/admin/device-admin.jd
@@ -48,6 +48,11 @@
provided by the Device Administration API to provide stronger security for
employee devices that are powered by Android.</p>
+<p class="note"><strong>Note</strong> For information on building a Work Policy
+Controller for Android for Work deployments, see <a
+href="{@docRoot}training/enterprise/work-policy-ctrl.html">Building a Work
+Policy Controller</a>.</p>
+
<h2 id="overview">Device Administration API Overview</h2>
@@ -712,4 +717,4 @@
</pre>
<p>
See the Device Administration API sample for a complete example of how to enable storage encryption.
-</p>
\ No newline at end of file
+</p>
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd
index f09ff9e..5710a47 100644
--- a/docs/html/guide/topics/data/backup.jd
+++ b/docs/html/guide/topics/data/backup.jd
@@ -643,7 +643,8 @@
// Allocate a helper and add it to the backup agent
@Override
public void onCreate() {
- SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
+ SharedPreferencesBackupHelper helper =
+ new SharedPreferencesBackupHelper(this, PREFS);
addHelper(PREFS_BACKUP_KEY, helper);
}
}
@@ -688,8 +689,10 @@
static final String FILES_BACKUP_KEY = "myfiles";
// Allocate a helper and add it to the backup agent
- void onCreate() {
- FileBackupHelper helper = new FileBackupHelper(this, TOP_SCORES, PLAYER_STATS);
+ @Override
+ public void onCreate() {
+ FileBackupHelper helper = new FileBackupHelper(this,
+ TOP_SCORES, PLAYER_STATS);
addHelper(FILES_BACKUP_KEY, helper);
}
}
diff --git a/docs/html/guide/topics/media/exoplayer.jd b/docs/html/guide/topics/media/exoplayer.jd
index 17b4669..1e8601f 100644
--- a/docs/html/guide/topics/media/exoplayer.jd
+++ b/docs/html/guide/topics/media/exoplayer.jd
@@ -72,10 +72,8 @@
<ul>
<li><a class="external-link" href="https://github.com/google/ExoPlayer/tree/master/library">
ExoPlayer Library</a> — This part of the project contains the core library classes.</li>
- <li><a class="external-link" href="https://github.com/google/ExoPlayer/tree/master/demo/src/main/java/com/google/android/exoplayer/demo/simple">
- Simple Demo</a> — This part of the app demonstrates a basic use of ExoPlayer.</li>
- <li><a class="external-link" href="https://github.com/google/ExoPlayer/tree/master/demo/src/main/java/com/google/android/exoplayer/demo/full">
- Full Demo</a> — This part of the app demonstrates more advanced features,
+ <li><a class="external-link" href="https://github.com/google/ExoPlayer/tree/master/demo">
+ Demo App</a> — This part of the project demonstrates usage of ExoPlayer,
including the ability to select between multiple audio tracks, a background audio mode,
event logging and DRM protected playback. </li>
</ul>
@@ -137,9 +135,10 @@
player.release(); // Don’t forget to release when done!
</pre>
-<p>For a complete example, see the {@code SimplePlayerActivity} in the ExoPlayer demo app, which
- correctly manages an ExoPlayer instance with respect to both the {@link android.app.Activity} and
- {@link android.view.Surface} lifecycles.</p>
+<p>For a complete example, see {@code PlayerActivity} and {@code DemoPlayer} in the ExoPlayer demo
+ app. Between them these classes correctly manage an ExoPlayer instance with respect to both the
+ {@link android.app.Activity} and {@link android.view.Surface} lifecycles.
+</p>
<h2 id="samplesource">SampleSource</h2>
@@ -187,7 +186,7 @@
</pre>
<p>The ExoPlayer demo app provides a complete implementation of this code in
- {@code DefaultRendererBuilder}. The {@code SimplePlaybackActivity} class uses it to play one
+ {@code DefaultRendererBuilder}. The {@code PlayerActivity} class uses it to play one
of the videos available in the demo app. Note that in the example, video and audio
are muxed, meaning they are streamed together from a single URI. The {@code FrameworkSampleSource}
instance provides video samples to the {@code videoRenderer} object and audio samples to the
@@ -211,9 +210,9 @@
which loads chunks of media data from which individual samples can be extracted. Each {@code
ChunkSampleSource} requires a {@code ChunkSource} object to be injected through its constructor,
which is responsible for providing media chunks from which to load and read samples. The {@code
- DashMp4ChunkSource} and {@code SmoothStreamingChunkSource} classes provide DASH and SmoothStreaming
- playback using the FMP4 container format. The {@code DashWebMChunkSource} class uses the WebM
- container format to provide DASH playback.</p>
+ DashChunkSource} class provides DASH playback using the FMP4 and WebM container formats. The
+ {@code SmoothStreamingChunkSource} class provides SmoothStreaming playback using the FMP4
+ container format.</p>
<p>All of the standard {@code ChunkSource} implementations require a {@code FormatEvaluator} and
a {@code DataSource} to be injected through their constructors. The {@code FormatEvaluator}
@@ -242,7 +241,7 @@
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent,
HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
-ChunkSource videoChunkSource = new DashMp4ChunkSource(videoDataSource,
+ChunkSource videoChunkSource = new DashChunkSource(videoDataSource,
new AdaptiveEvaluator(bandwidthMeter), videoRepresentations);
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource,
loadControl, VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
@@ -253,7 +252,7 @@
// Build the audio renderer.
DataSource audioDataSource = new HttpDataSource(userAgent,
HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
-ChunkSource audioChunkSource = new DashMp4ChunkSource(audioDataSource,
+ChunkSource audioChunkSource = new DashChunkSource(audioDataSource,
new FormatEvaluator.FixedEvaluator(), audioRepresentation);
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource,
loadControl, AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
@@ -273,9 +272,8 @@
</p>
<p>The ExoPlayer demo app provides complete implementation of this code in
- {@code DashVodRendererBuilder}. The {@code SimplePlaybackActivity} class uses this builder to
- construct renderers for playing DASH sample videos in the demo app. It asynchronously fetches a
- specified MPD file in order to construct the required {@code Representation} objects. For an
+ {@code DashRendererBuilder}. The {@code PlayerActivity} class uses this builder to
+ construct renderers for playing DASH sample videos in the demo app. For an
equivalent SmoothStreaming example, see the {@code SmoothStreamingRendererBuilder} class in the
demo app.</p>
@@ -313,7 +311,7 @@
}
</pre>
-<p>This approach is used to filter {@code Representations} in the {@code DashVodRendererBuilder}
+<p>This approach is used to filter {@code Representations} in the {@code DashRendererBuilder}
class of the ExoPlayer demo app, and similarly to filter track indices in {@code
SmoothStreamingRendererBuilder}.</p>
@@ -372,24 +370,26 @@
<p>In addition to high level listeners, many of the individual components provided by the
ExoPlayer library allow their own event listeners. For example, {@code
MediaCodecVideoTrackRenderer} has constructors that take a {@code
- MediaCodecVideoTrackRenderer.EventListener}. In the ExoPlayer demo app, {@code SimplePlayerActivity}
- acts as a listener so that it can adjust the dimensions of the target surface to have the correct
- height and width ratio for the video being played:</p>
+ MediaCodecVideoTrackRenderer.EventListener}. In the ExoPlayer demo app, {@code DemoPlayer}
+ acts as the listener to multiple individual components, forwarding events to {@code PlayerActivity}.
+ This approach allows {@code PlayerActivity} to adjust the dimensions of the target surface
+ to have the correct height and width ratio for the video being played:</p>
<pre>
@Override
-public void onVideoSizeChanged(int width, int height) {
- surfaceView.setVideoWidthHeightRatio(height == 0 ? 1 : (float) width / height);
+public void onVideoSizeChanged(int width, int height, float pixelWidthAspectRatio) {
+ surfaceView.setVideoWidthHeightRatio(
+ height == 0 ? 1 : (width * pixelWidthAspectRatio) / height);
}
</pre>
-<p>The {@code RendererBuilder} classes in the ExoPlayer demo app inject the activity as the
- listener, for example in the {@code DashVodRendererBuilder} class:</p>
+<p>The {@code RendererBuilder} classes in the ExoPlayer demo app inject the {@code DemoPlayer} as
+ the listener to each component, for example in the {@code DashRendererBuilder} class:</p>
<pre>
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(
- videoSampleSource, null, true, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT,
- 0, <strong>mainHandler, playerActivity</strong>, 50);
+ sampleSource, null, true, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000,
+ null, <strong>player.getMainHandler(), player</strong>, 50);
</pre>
<p>Note that you must pass a {@link android.os.Handler} object to the renderer, which determines
@@ -441,9 +441,7 @@
<p>You must use a blocking message because the contract of {@link
android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed()} requires that the
- app does not attempt to access the surface after the method returns. The {@code
- SimplePlayerActivity} class in the demo app demonstrates how the surface should be set and
- cleared.</p>
+ app does not attempt to access the surface after the method returns.</p>
<h2 id="customizing">Customizing ExoPlayer</h2>
diff --git a/docs/html/guide/topics/resources/available-resources.jd b/docs/html/guide/topics/resources/available-resources.jd
index 19babee..db1bf8d 100644
--- a/docs/html/guide/topics/resources/available-resources.jd
+++ b/docs/html/guide/topics/resources/available-resources.jd
@@ -29,6 +29,7 @@
<dt><a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a></dt>
<dd>Define various graphics with bitmaps or XML.<br/>
Saved in {@code res/drawable/} and accessed from the {@code R.drawable} class.</dd>
+
<dt><a href="{@docRoot}guide/topics/resources/layout-resource.html">Layout Resource</a></dt>
<dd>Define the layout for your application UI.<br/>
Saved in {@code res/layout/} and accessed from the {@code R.layout} class.</dd>
diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd
index 1ee6606..0a96a15 100644
--- a/docs/html/guide/topics/resources/localization.jd
+++ b/docs/html/guide/topics/resources/localization.jd
@@ -433,8 +433,8 @@
<p>To change the locale in the emulator by using the adb shell. </p>
<ol>
- <li>Pick the locale you want to test and determine its language and region codes, for
-example <code>fr</code> for French and <code>CA</code> for Canada.<br>
+ <li>Pick the locale you want to test and determine its BCP-47 language tag, for
+example, Canadian French would be <code>fr-CA</code>.<br>
</li>
<li>Launch an emulator.</li>
<li>From a command-line shell on the host computer, run the following
@@ -444,16 +444,14 @@
the <code>-e</code> option:<br>
<code>adb -e shell</code></li>
<li>At the adb shell prompt (<code>#</code>), run this command: <br>
- <code>setprop persist.sys.language [<em>language code</em>];setprop
-persist.sys.country [<em>country code</em>];stop;sleep 5;start <br>
+ <code>setprop persist.sys.locale [<em>BCP-47 language tag</em>];stop;sleep 5;start <br>
</code>Replace bracketed sections with the appropriate codes from Step
1.</li>
</ol>
<p>For instance, to test in Canadian French:</p>
-<p><code>setprop persist.sys.language fr;setprop persist.sys.country
-CA;stop;sleep 5;start </code></p>
+<p><code>setprop persist.sys.locale fr-CA;stop;sleep 5;start </code></p>
<p>This will cause the emulator to restart. (It will look like a full reboot,
but it is not.) Once the Home screen appears again, re-launch your application (for
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 6d9527f..fc79970 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -60,18 +60,24 @@
MyActivity.java </span>
res/
drawable/ <span style="color:black">
- icon.png </span>
+ graphic.png </span>
layout/ <span style="color:black">
main.xml
info.xml</span>
+ mipmap/ <span style="color:black">
+ icon.png </span>
values/ <span style="color:black">
strings.xml </span>
</pre>
<p>As you can see in this example, the {@code res/} directory contains all the resources (in
-subdirectories): an image resource, two layout resources, and a string resource file. The resource
+subdirectories): an image resource, two layout resources, {@code mipmap/} directories for launcher
+icons, and a string resource file. The resource
directory names are important and are described in table 1.</p>
+<p class="note"><strong>Note:</strong> For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
+
<p class="table-caption" id="table1"><strong>Table 1.</strong> Resource directories
supported inside project {@code res/} directory.</p>
@@ -104,6 +110,7 @@
<tr>
<td><code>drawable/</code></td>
+
<td><p>Bitmap files ({@code .png}, {@code .9.png}, {@code .jpg}, {@code .gif}) or XML files that
are compiled into the following drawable resource subtypes:</p>
<ul>
@@ -119,6 +126,13 @@
</tr>
<tr>
+ <td><code>mipmap/</code></td>
+ <td>Drawable files for different launcher icon densities. For more information on managing
+ launcher icons with {@code mipmap/} folders, see
+ <a href="{@docRoot}tools/project/index.html#mipmap">Managing Projects Overview</a>.</td>
+ </tr>
+
+ <tr>
<td><code>layout/</code></td>
<td>XML files that define a user interface layout.
See <a href="layout-resource.html">Layout Resource</a>.</td>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index e47c77e..976115e 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -663,20 +663,21 @@
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
- new Intent(new ComponentName(this, ResultActivity.class));
+ new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
-notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
-PendingIntent notifyIntent =
+PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
- notifyIntent
+ notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
-builder.setContentIntent(notifyIntent);
+builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
@@ -715,7 +716,7 @@
<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
<p>
To display a determinate progress bar, add the bar to your notification by calling
- {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
increment <code>progress</code>, and update the notification. At the end of the operation,
<code>progress</code> should equal <code>max</code>. A common way to call
@@ -727,7 +728,7 @@
You can either leave the progress bar showing when the operation is done, or remove it. In
either case, remember to update the notification text to show that the operation is complete.
To remove the progress bar, call
- {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress
setProgress(0, 0, false)}. For example:
</p>
<pre>
@@ -783,8 +784,8 @@
<p>
Issue the notification at the beginning of the operation. The animation will run until you
modify your notification. When the operation is done, call
- {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
- setProgress(0, 0, false)} and then update the notification to remove the activity indicator.
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, false)}
+ and then update the notification to remove the activity indicator.
Always do this; otherwise, the animation will run even when the operation is complete. Also
remember to change the notification text to indicate that the operation is complete.
</p>
diff --git a/docs/html/images/enterprise/work-launcher.png b/docs/html/images/enterprise/work-launcher.png
new file mode 100644
index 0000000..3bbd835
--- /dev/null
+++ b/docs/html/images/enterprise/work-launcher.png
Binary files differ
diff --git a/docs/html/images/exoplayer/adaptive-streaming.png b/docs/html/images/exoplayer/adaptive-streaming.png
index 9fc650c9..50eee70 100644
--- a/docs/html/images/exoplayer/adaptive-streaming.png
+++ b/docs/html/images/exoplayer/adaptive-streaming.png
Binary files differ
diff --git a/docs/html/images/tools/projectview-p1.png b/docs/html/images/tools/projectview-p1.png
new file mode 100644
index 0000000..f5fae63
--- /dev/null
+++ b/docs/html/images/tools/projectview-p1.png
Binary files differ
diff --git a/docs/html/images/tools/projectview-p2.png b/docs/html/images/tools/projectview-p2.png
new file mode 100644
index 0000000..9e52540
--- /dev/null
+++ b/docs/html/images/tools/projectview-p2.png
Binary files differ
diff --git a/docs/html/images/tools/studio-inspections-config.png b/docs/html/images/tools/studio-inspections-config.png
new file mode 100644
index 0000000..e41afa1
--- /dev/null
+++ b/docs/html/images/tools/studio-inspections-config.png
Binary files differ
diff --git a/docs/html/images/tools/studio-mipmap-folders.png b/docs/html/images/tools/studio-mipmap-folders.png
new file mode 100644
index 0000000..3e99180
--- /dev/null
+++ b/docs/html/images/tools/studio-mipmap-folders.png
Binary files differ
diff --git a/docs/html/images/tools/studio-project-layout.png b/docs/html/images/tools/studio-project-layout.png
index 880c233..7339c3f 100644
--- a/docs/html/images/tools/studio-project-layout.png
+++ b/docs/html/images/tools/studio-project-layout.png
Binary files differ
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index 6fb906e..9caf938 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -1186,5 +1186,21 @@
"training/multiscreen/index.html",
"training/monitoring-device-state/index.html"
]
+ },
+ "training/work/apps": {
+ "title": "",
+ "resources": [
+ "training/enterprise/app-compatibility.html",
+ "training/enterprise/app-restrictions.html",
+ "samples/AppRestrictionSchema/index.html",
+ "samples/AppRestrictionEnforcer/index.html"
+ ]
+ },
+ "training/work/admin": {
+ "title": "",
+ "resources": [
+ "training/enterprise/work-policy-ctrl.html",
+ "samples/BasicManagedProfile/index.html"
+ ]
}
}
\ No newline at end of file
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index af6f6b8..a43ba3c 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -4,27 +4,27 @@
header.hide=1
page.metaDescription=Download the official Android IDE and developer tools to build apps for Android phones, tablets, wearables, TVs, and more.
-studio.version=1.0.1
+studio.version=1.1.0
-studio.linux_bundle_download=android-studio-ide-135.1641136-linux.zip
-studio.linux_bundle_bytes=243917559
-studio.linux_bundle_checksum=7c8f2d0cec21b98984cdba45ab5a25f26d67f23a
+studio.linux_bundle_download=android-studio-ide-135.1740770-linux.zip
+studio.linux_bundle_bytes=259336386
+studio.linux_bundle_checksum=e8d166559c50a484f83ebfec6731cc0e3f259208
-studio.mac_bundle_download=android-studio-ide-1641136.dmg
-studio.mac_bundle_bytes=245729073
-studio.mac_bundle_checksum=49506ba2cf6b56be4f7d07e6a00c4ec3ba2249d5
+studio.mac_bundle_download=android-studio-ide-135.1740770-mac.dmg
+studio.mac_bundle_bytes=261303345
+studio.mac_bundle_checksum=f9745d0fec1eefd498f6160a2d6a1b5247d4cda3
-studio.win_bundle_exe_download=android-studio-bundle-135.1641136.exe
-studio.win_bundle_exe_bytes=868344232
-studio.win_bundle_exe_checksum=9c1c8ea6aa17fb74e0593c62fd48ee62a8950be7
+studio.win_bundle_exe_download=android-studio-bundle-135.1740770-windows.exe
+studio.win_bundle_exe_bytes=856233768
+studio.win_bundle_exe_checksum=7484b9989d2914e1de30995fbaa97a271a514b3f
-studio.win_notools_exe_download=android-studio-ide-135.1641136.exe
-studio.win_notools_exe_bytes=260272840
-studio.win_notools_exe_checksum=464d1c5497ab3d1bdef441365791ab36c89cd5ae
+studio.win_notools_exe_download=android-studio-ide-135.1740770-windows.exe
+studio.win_notools_exe_bytes=242135128
+studio.win_notools_exe_checksum=5ea77661cd2300cea09e8e34f4a2219a0813911f
-studio.win_bundle_download=android-studio-ide-135.1641136-windows.zip
-studio.win_bundle_bytes=246249059
-studio.win_bundle_checksum=6d6856aca83f6ff747ca40b10f70edfbbcccd91c
+studio.win_bundle_download=android-studio-ide-135.1740770-windows.zip
+studio.win_bundle_bytes=261667054
+studio.win_bundle_checksum=e903f17cc6a57c7e3d460c4555386e3e65c6b4eb
diff --git a/docs/html/sdk/installing/adding-packages.jd b/docs/html/sdk/installing/adding-packages.jd
index b8d8925..58a8065 100644
--- a/docs/html/sdk/installing/adding-packages.jd
+++ b/docs/html/sdk/installing/adding-packages.jd
@@ -72,7 +72,7 @@
<li>Windows: Double-click the <code>SDK Manager.exe</code> file at the root of the Android
SDK directory.</li>
<li>Mac/Linux: Open a terminal and navigate to the <code>tools/</code> directory in the
- Android SDK, then execute <code>android sdk</code>.</li>
+ location where the Android SDK was installed, then execute <code>android sdk</code>.</li>
</ul>
</li>
</ul>
diff --git a/docs/html/sdk/installing/create-project.jd b/docs/html/sdk/installing/create-project.jd
index 5082537..68fd572 100644
--- a/docs/html/sdk/installing/create-project.jd
+++ b/docs/html/sdk/installing/create-project.jd
@@ -71,7 +71,7 @@
<h3 id="Step2SelectFormFactor">Step 2: Select Form Factors and API Level</h2>
<p>The next window lets you select the form factors supported by your app, such as phone, tablet,
-TV, Wear, and Google Glass. The selected form factors become the application modules witin the
+TV, Wear, and Google Glass. The selected form factors become the application modules within the
project. For each form factor, you can also select the API Level for that app. To get more information,
click <strong>Help me choose</strong>.</p>
@@ -220,7 +220,7 @@
along with the other modules. </p>
<p> You can easily change an existing application module to a library module by changing the
- plugin assignment in the <strong>build.gradle</strong> file to <em>com.android.libary</em>.</p>
+ plugin assignment in the <strong>build.gradle</strong> file to <em>com.android.library</em>.</p>
<pre>
apply plugin: 'com.android.application'
@@ -287,7 +287,7 @@
<ol>
<li>Make sure that both the module library and the application module that depends on it are
- in your proejct. If one of the modules is missing, import it into your project.</li>
+ in your project. If one of the modules is missing, import it into your project.</li>
<li>In the project view, right-click the dependent module and select
<strong>Open</strong> > <strong>Module Settings</strong>.</li>
@@ -359,39 +359,38 @@
per resource type.</li>
</ul>
-<div style="float:right;margin-left:30px;width:240px">
-<img src="{@docRoot}images/tools/projectview01.png" alt="" width="220" height="264"/>
-<p class="img-caption"><strong>Figure 9:</strong> Show the Android project view.</p>
-</div>
-<h2 id="enable-view">Enable and use the Android Project View</h2>
+<h2 id="enable-view">Use the Android Project View</h2>
-<p>The Android project view is not yet enabled by default. To show the Android project view,
-click <strong>Project</strong> and select <strong>Android</strong>, as shown in figure 9.</p>
-
-<p>The Android project view shows all the build files at the top level of the project hierarchy
-under <strong>Gradle Scripts</strong>. Each project module appears as a folder at the top
-level of the project hierarchy and contains these three elements at the top level:</p>
+<p>The <em>Android</em> project view is enabled by default and shows all the build files at
+the top level of the project hierarchy under <strong>Gradle Scripts</strong>. The project module
+appears as a folder at the top level of the project hierarchy and contains these three elements
+at the top level:</p>
<ul>
-<li><code>java/</code> - Source files for the module.</li>
<li><code>manifests/</code> - Manifest files for the module.</li>
+<li><code>java/</code> - Source files for the module.</li>
<li><code>res/</code> - Resource files for the module.</li>
</ul>
-<p>Figure 10 shows how the Android project view groups all the instances of the
+<p>Notice how the Android project view groups all instances of the
<code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
<p class="note"><strong>Note:</strong> The Android project view shows a hierarchy that helps you
work with Android projects by providing a flattened structure that highlights the most commonly
used files while developing Android applications. However, the project structure on disk differs
-from this representation.</p>
+from this representation and maintains the traditional project structure.</p>
-<img src="{@docRoot}images/tools/projectview03.png" alt=""
- style="margin-top:10px" width="650" height="508"/>
-<p class="img-caption"><strong>Figure 10:</strong> The traditional project view (left) and the
-Android project view (right).</p>
+<img src="{@docRoot}images/tools/projectview-p1.png" alt="" style="width:240px" "/>
+
+<img src="{@docRoot}images/tools/projectview-p2.png" alt="" style="width:240px" " />
+<p class="img-caption"><strong>Figure 10:</strong> Android and Traditional project view </p>
+
+
+
+
+
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index ee3bd95..d899ef3 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -121,7 +121,12 @@
<p>You may want to add {@code android-studio/bin/} to your PATH environmental
variable so that you can start Android Studio from any directory.</p>
</li>
- <li>Follow the setup wizard to install any necessary SDK tools.</li>
+ <li>If the SDK is not already installed, follow the setup wizard to install the SDK and any
+ necessary SDK tools.
+ <p class="note"><strong>Note:</strong> You may also need to install the ia32-libs,
+ lib32ncurses5-dev, and lib32stc++6 packages. These packages are required to support 32-bit apps
+ on a 64-bit machine. </p>
+ </li>
</ol>
</div><!-- end linux -->
diff --git a/docs/html/tools/debugging/debugging-ui.jd b/docs/html/tools/debugging/debugging-ui.jd
index f927d08..cf7e3ba 100644
--- a/docs/html/tools/debugging/debugging-ui.jd
+++ b/docs/html/tools/debugging/debugging-ui.jd
@@ -34,17 +34,17 @@
<h2>Related videos</h2>
<ol>
<li>
-<iframe title="Hierarchyviewer"
- width="210" height="160"
- src="//www.youtube.com/embed/PAgE7saQUUY?rel=0&hd=1"
+<iframe title="Hierarchyviewer"
+ width="210" height="160"
+ src="//www.youtube.com/embed/PAgE7saQUUY?rel=0&hd=1"
frameborder="0" allowfullscreen>
</iframe>
</li>
<li>
-<iframe title="Pixel Perfect"
- width="210" height="160"
- src="//www.youtube.com/embed/C45bMZGdN7Y?rel=0&hd=1"
- frameborder="0"
+<iframe title="Pixel Perfect"
+ width="210" height="160"
+ src="//www.youtube.com/embed/C45bMZGdN7Y?rel=0&hd=1"
+ frameborder="0"
allowfullscreen>
</iframe>
</li>
@@ -52,11 +52,10 @@
</div>
</div>
- <p>
-Sometimes your application's layout can slow down your application.
- To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and
- <code>lint</code> tools.
- </p>
+
+<p>Sometimes your application's layout can slow down your application.
+To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and
+<code><a href="{@docRoot}tools/help/lint.html">lint</a></code> tools. </p>
<p>The Hierarchy Viewer application allows you to debug and optimize your user interface. It
provides a visual representation of the layout's View hierarchy (the View Hierarchy window)
@@ -64,8 +63,10 @@
and a magnified view of the display (the Pixel Perfect window) to closely examine the pixels
in your layout.</p>
- <p>Android <code>lint</code> is a static code scanning tool that helps you optimize the layouts and layout
- hierarchies of your applications, as well as detect other common coding problems. You can run it against your layout files or resource
+ <p>Android <code><a href="{@docRoot}tools/help/lint.html">lint</a></code> is a static code
+ scanning tool that helps you optimize the layouts and layout
+ hierarchies of your applications, as well as detect other common coding problems. You can run it
+ against your layout files or resource
directories to quickly check for inefficiencies or other types of problems that could be
affecting the performance of your application.</p>
@@ -493,7 +494,10 @@
alt=""
height="600"/>
<p class="img-caption"><strong>Figure 4.</strong> The Pixel Perfect window</p>
+
+
<h2 id="lint">Using lint to Optimize Your UI</h2>
-<p>The Android {@code lint} tool lets you analyze the XML files that define your application's UI to find inefficiencies in the view hierarchy.</p>
-<p class="note"><strong>Note: </strong>The Android <code>layoutopt</code> tool has been replaced by the {@code lint} tool beginning in ADT and SDK Tools revision 16. The {@code lint} tool reports UI layout performance issues in a similar way as <code>layoutopt</code>, and detects additional problems.</p>
-<p>For more information about using {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a> and the <a href="{@docRoot}tools/help/lint.html">lint reference documentation</a>.</p>
+<p>The Android <a href="{@docRoot}tools/help/lint.html">lint</a> tool lets you analyze the XML
+files that define your application's UI to find inefficiencies in the view hierarchy.</p>
+<p class="note"><strong>Note: </strong>The Android <code>layoutopt</code> tool has been replaced by the {@code lint} tool beginning in SDK Tools revision 16. The {@code lint} tool reports UI layout performance issues in a similar way as <code>layoutopt</code>, and detects additional problems.</p>
+<p>For more information about using {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a> and the <a href="{@docRoot}tools/help/lint.html">lint tools help</a>.</p>
diff --git a/docs/html/tools/debugging/improving-w-lint.jd b/docs/html/tools/debugging/improving-w-lint.jd
index 7e238fa..ff94b7f 100644
--- a/docs/html/tools/debugging/improving-w-lint.jd
+++ b/docs/html/tools/debugging/improving-w-lint.jd
@@ -9,11 +9,11 @@
<ol>
<li><a href="#overview">Overview</a></li>
- <li><a href=#eclipse">Running lint from Eclipse</a></li>
+ <li><a href=#studio">Running lint from Android Studio</a></li>
<li><a href=#commandline">Running lint from the command-line</a></li>
<li><a href=#config">Configuring lint</a>
<ol>
- <LI><a href="#eclipse_config">Configuring lint in Eclipse</a></LI>
+ <LI><a href="#studio_config">Configuring lint in Android Studio</a></LI>
<LI><a href="#pref">Configuring the lint file</a></LI>
<LI><a href="#src">Configuring lint checking in Java and XML source files</a></LI>
</ol>
@@ -31,8 +31,15 @@
In addition to testing that your Android application meets its functional requirements, it's important to ensure that your code has no structural problems. Poorly structured code can impact the reliability and efficiency of your Android apps and make your code harder to maintain. For example, if your XML resource files contain unused namespaces, this takes up space and incurs unnecessary processing. Other structural issues, such as use of deprecated elements or API calls that are not supported by the target API versions, might lead to code failing to run correctly.</p>
<h2 id="overview">Overview</h2>
-<p>The Android SDK provides a code scanning tool called {@code lint} that can help you to easily identify and correct problems with the structural quality of your code, without having to execute the app or write any test cases. Each problem detected by the tool is reported with a description message and a severity level, so that you can quickly prioritize the critical improvements that need to be made. You can also configure a problem's severity level to ignore issues that are not relevant for your project, or raise the severity level. The tool has a command-line interface, so you can easily integrate it into your automated testing process.</p>
-<p>The {@code lint} tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. You can run {@code lint} from the command-line or from the Eclipse environment.</p>
+<p>The Android SDK provides a code scanning tool called <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a>
+that can help you to easily identify and correct problems with the structural quality of your code, without having to execute the app or write any test cases. Each problem detected by the tool is reported with a description message and a severity level, so that you can quickly prioritize the critical improvements that need to be made. You can also configure a problem's severity level to ignore issues that are not relevant for your project, or raise the severity level. The tool has a command-line interface, so you can easily integrate it into your automated testing process.</p>
+<p>The {@code lint} tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. You can run {@code lint} from the command-line or from Android Studio.</p>
+
+<p class="note"><strong>Note:</strong> In Android Studio, additional
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a> run when your code is compiled in Android Studio to
+streamline code review.</p>
+
<p>Figure 1 shows how the {@code lint} tool processes the application source files.</p>
<img id="Fig1" src="{@docRoot}images/tools/lint.png" alt="">
<p class="img-caption"><strong>Figure 1.</strong> Code scanning workflow with the {@code lint} tool</p>
@@ -42,25 +49,51 @@
<dt><b>The <code>lint.xml</code> file</b></dt>
<dd>A configuration file that you can use to specify any {@code lint} checks that you want to exclude and to customize problem severity levels.</dd>
<dt><b>The {@code lint} tool</b></dt>
-<dd>A static code scanning tool that you can run on your Android project from the command-line or from Eclipse. The {@code lint} tool checks for structural code problems that could affect the quality and performance of your Android application. It is strongly recommended that you correct any errors that {@code lint} detects before publishing your application.</dd>
+<dd>A static code scanning tool that you can run on your Android project from the command-line or Android Studio. The {@code lint} tool checks for structural code problems that could affect the quality and performance of your Android application. It is strongly recommended that you correct any errors that {@code lint} detects before publishing your application.</dd>
<dt><b>Results of {@code lint} checking</b></dt>
-<dd>You can view the results from {@code lint} in the console or in the <strong>Lint Warnings</strong> view in Eclipse. Each issue is identified by the location in the source files where it occurred and a description of the issue.</dd>
+<dd>You can view the results from {@code lint} in the console or in the <strong>Event Log</strong> in Android Studio. Each issue is identified by the location in the source files where it occurred and a description of the issue.</dd>
</dl>
-<p>The {@code lint} tool is automatically installed as part of the Android SDK Tools revision 16 or higher. If you want to use {@code lint} in the Eclipse environment, you must also install the Android Development Tools (ADT) Plugin for Eclipse revision 16 or higher. For more information about installing the SDK or the ADT Plugin for Eclipse, see <a href="http://developer.android.com/sdk/installing.html">Installing the SDK.</a></p>
+<p>The {@code lint} tool is automatically installed as part of the Android SDK Tools revision 16 or higher.</p>
-<h2 id="eclipse">Running lint from Eclipse</h2>
-<p>If the ADT Plugin is installed in your Eclipse environment, the {@code lint} tool runs automatically when you perform one of these actions:</p>
-<ul>
-<LI>Export an APK</LI>
-<LI>Edit and save an XML source file in your Android project (such as a manifest or layout file)</LI>
-<LI>Use the layout editor in Eclipse to make changes</LI>
-</ul>
-<p>Note that when you export an APK, {@code lint} only runs an automatic check for fatal errors and aborts the export if fatal errors are found. You can turn off this automatic checking from the <strong>Lint Error Checking</strong> page in Eclipse Preferences. </p>
-<p>The output is displayed in the <strong>Lint Warnings</strong> view. If the <strong>Lint Warnings</strong> view is not showing in the workbench, you can bring it up from the Eclipse menu by clicking <strong>Window > Show View > Other > Android > Lint Warnings</strong>.</p>
-<p>Figure 2 shows an example of the output in the Lint Warnings view.</p>
-<img id="Fig2" src="{@docRoot}images/tools/lint_output.png" alt="">
-<p class="img-caption"><strong>Figure 2.</strong> Sample output in the <strong>Lint Warnings</strong> view</p>
-<p>You can also run a {@code lint} scan manually on your Android project in Eclipse by right-clicking on the project folder in the Package Explorer > <strong>Android Tools > Run Lint: Check for Common Errors</strong>.</p>
+
+<h2 id="studio">Running lint in Android Studio</h2>
+<p>In Android Studio, the configured <code>lint</code> and
+IDE inspections run automatically whenever you build your app. The IDE inspections are
+configured along with the {@code lint} checks to run
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a> to streamline code review.</p>
+
+<p class="note"><strong>Note:</strong> To view and modify inspection severity
+levels, use the <strong>File > Settings > Project Settings</strong> menu to open the
+<em>Inspection Configuration</em> page with a list of the supported inspections.</p>
+
+
+<p>With Android Studio, you can also run {@code lint} inspections for a specific build variant,
+or for all build variants from the <code>build.gradle</code> file. Add the
+<code>lintOptions</code> property to the <code>android</code> settings in the build file.
+This code snippet from a Gradle build file shows how to set the <code>quiet</code> option to
+<code>true</code> and the <code>abortOnError</code> option to <code>false</code>. </p>
+
+<pre>
+android {
+ lintOptions {
+ // set to true to turn off analysis progress reporting by lint
+ quiet true
+ // if true, stop the gradle build if errors are found
+ abortOnError false
+ // if true, only report errors
+ ignoreWarnings true
+ }
+ ...
+ }
+</pre>
+
+
+<p>To manually run inspections in Android Studio, from the application or right-click menu,
+choose <strong>Analyze > Inspect Code</strong>. The <em>Specify Inspections Scope</em> dialog
+appears so you can specify the desired inspection scope and profile.</p>
+
+
<h2 id="commandline">Running lint from the Command-Line</h2>
@@ -96,38 +129,45 @@
<p>By default, when you run a {@code lint} scan, the tool checks for all issues that are supported by {@code lint}. You can also restrict the issues for {@code lint} to check and assign the severity level for those issues. For example, you can disable {@code lint} checking for specific issues that are not relevant to your project and configure {@code lint} to report non-critical issues at a lower severity level.</p>
<p>You can configure {@code lint} checking at different levels:</p>
<ul>
-<LI>Globally, for all projects</LI>
-<li>Per project</li>
-<li>Per file</li>
-<li>Per Java class or method (by using the <code>@SuppressLint</code> annotation), or per XML element (by using the <code>tools:ignore</code> attribute.</li>
+<LI>Globally, for the entire project</LI>
+<li>Per project module</li>
+<li>Per production module</li>
+<li>Per test module</li>
+<li>Per open files</li>
+<li>Per class hierarchy</li>
+<li>Per Version Control System (VCS) scopes</li>
</ul>
-<h3 id="eclipse_config">Configuring lint in Eclipse</h3>
-<p>You can configure global, project-specific, and file-specific settings for {@code lint} from the Eclipse user interface.</p>
+<h3 id="studio_config">Configuring lint in Android Studio</h3>
+<p>Android Studio allows you to enable or disable individual inspections and configure
+project-global, directory-specific, and file-specific settings for {@code lint}.</p>
+
+<p>You can manage inspection profiles and configure inspection severity within Android Studio using
+the <strong>File > Settings > Project Settings</strong> menu to open the <em>Inspections</em>
+page with a list of the supported profiles and inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 3.</strong> Inspection Configuration</p>
<h4>Global preferences</h4>
<ol>
-<LI>Open <strong>Window > Preferences > Android > Lint Error Checking</strong>.</LI>
-<li>Specify your preferences and click <b>OK</b>.</li>
-</ol>
-<p>These settings are applied by default when you run {@code lint} on your Android projects in Eclipse.</p>
+<li>To specify global project settings, select the project folder in the Project View and choose
+<strong>Analyze > Inspect Code</strong>.</li>
-<h4>Project and file-specific preferences</h4>
-<ol>
-<LI>Run the {@code lint} tool on your project by right-clicking on your project folder in the Package Explorer and selecting <strong>Android Tools > Run Lint: Check for Common Errors</strong>. This action brings up the <strong>Lint Warnings</strong> view which displays a list of issues that {@code lint} detected in your project.</LI>
-<li>From the <strong>Lint Warnings</strong> view, use the toolbar options to configure {@code lint} preferences for individual projects and files in Eclipse. The options you can select include:
-<ul>
-<LI><b>Suppress this error with an annotation/attribute</b> - If the issue appears in a Java class, the {@code lint} tool adds a <code>@SuppressLint</code> annotation to the method where the issue was detected. If the issue appears in an {@code .xml} file, {@code lint} inserts a <code>tools:ignore</code> attribute to disable checking for the {@code lint} issue in this file.</LI>
-<LI><b>Ignore in this file</b> - Disables checking for this {@code lint} issue in this file.</LI>
-<li><b>Ignore in this project</b> - Disables checking for this {@code lint} issue in this project.</li>
-<li><b>Always ignore</b> - Disables checking for this {@code lint} issue globally for all projects.</li>
-</ul>
-</li>
+<li>Specify your inspection scope and profile, and click <b>OK</b>.</li>
</ol>
-<p>If you select the second or third option, the {@code lint} tool automatically generates a <code>lint.xml</code> file with these configuration settings in your Android application project folder. </p>
+<p>The configured settings run the specified {@code lint} inspections. The {@code lint}
+inspections are also run whenever you build and run your Android project and modules.</p>
+
+<h4>Module and file-specific preferences</h4>
+<ol>
+<LI>Run the {@code lint} tool on your module by right-clicking on your module folder or file in the Project View and selecting <strong>Analyze > Inspect Code</strong>. This displays the {@code lint} inspection results
+with a list of issues that {@code lint} detected in your module.</LI>
+<li>From the <strong>Lint Warnings</strong> view, use the toolbar options to configure {@code lint} preferences for individual modules and files, and set the issue display options.</li>
+</ol>
+
<h3 id="pref">Configuring the lint file</h3>
-<p>You can specify your {@code lint} checking preferences in the <code>lint.xml</code> file. If you are creating this file manually, place it in the root directory of your Android project. If you are configuring {@code lint} preferences in Eclipse, the <code>lint.xml</code> file is automatically created and added to your Android project for you.</p>
+<p>You can specify your {@code lint} checking preferences in the <code>lint.xml</code> file. If you are creating this file manually, place it in the root directory of your Android project. If you are configuring {@code lint} preferences in Android Studio, the <code>lint.xml</code> file is automatically created and added to your Android project for you.</p>
<p>The <code>lint.xml</code> file consists of an enclosing <code><lint></code> parent tag that contains one or more children <code><issue></code> elements. Each <code><issue></code> is identified by a unique <code>id</code> attribute value, which is defined by {@code lint}.</p>
<pre>
<?xml version="1.0" encoding="UTF-8"?>
@@ -165,12 +205,9 @@
<h3 id="src">Configuring lint checking in Java and XML source files</h3>
<p>You can disable {@code lint} checking from your Java and XML source files.</p>
-<p class="note"><strong>Tip: </strong>If you are using Eclipse, you can use the <strong>Quick Fix</strong> feature to automatically add the annotation or attribute to disable {@code lint} checking to your Java or XML source files:
-<ol>
-<LI>Open the Java or XML file that has a {@code lint} warning or error in an Eclipse editor.</LI>
-<LI>Move your cursor to the location in the file where is {@code lint} issue is found, then press <code>Ctrl+1</code> to bring up the <strong>Quick Fix</strong> pop-up.</LI>
-<li>From the <strong>Quick Fix</strong> pop-up, select the action to add an annotation or attribute to ignore the {@code lint} issue.</li>
-</ol>
+<p class="note"><strong>Tip: </strong>If you are using Android Studio, you can use the
+<strong>File > Settings > Project Settings > Inspections</strong> feature to manage the
+{@code lint} checking to your Java or XML source files.
</p>
<h4>Configuring lint checking in Java</h4>
diff --git a/docs/html/tools/help/lint.jd b/docs/html/tools/help/lint.jd
index ba31f6d..0f52689 100644
--- a/docs/html/tools/help/lint.jd
+++ b/docs/html/tools/help/lint.jd
@@ -14,14 +14,23 @@
</div>
</div>
-<p>The Android {@code lint} tool is a static code analysis tool that checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization. </p>
-<p>For more information on running {@code lint}, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+<p>The Android {@code lint} tool is a static code analysis tool that checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization.</p>
-<h2 id="syntax">Syntax</h2>
+<p>In Android Studio, the configured <code>lint</code> and other IDE inspections run automatically
+whenever you compile your program. You can also manually run inspections in Android Studio
+by selecting <strong>Analyze > Inspect Code</strong> from the application or right-click menu.
+The <em>Specify Inspections Scope</em> dialog appears so you can specify the desired inspection
+profile and scope.</p>
+
+<p>For more information on enabling {@code lint} inspections and running {@code lint},
+see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+
+<h2 id="syntax">Command Line Syntax</h2>
<p>
<pre>lint [flags] <project directory></pre>
-For example, you can issue the following command to scan the Java and XML files under the {@code myproject} directory and its subdirectories. The result is displayed on the console.
+For example, you can issue the following command to scan the Java and XML files under the
+{@code myproject} directory and its subdirectories. The result is displayed on the console.
<pre>lint myproject</pre>
You can also use {@code lint} to check for a specific issue. For example, you can run the following command to scan the files under the {@code myproject} directory and its subdirectories to check for XML attributes missing the Android namespace prefix. The issue ID {@code MissingPrefix} tells lint to only scan for this issue.
@@ -172,7 +181,11 @@
<h2 id="config_keywords">Configuring Java and XML Source Files</h2>
<p>To configure lint checking, you can apply the following annotation or attribute to the source files in your Android project. </p>
<ul>
-<LI>To disable lint checking for a specific Java class or method, use the <code>@SuppressLint</code> annotation. </LI>
-<li>To disable lint checking for specific sections of your XML file, use the <code>tools:ignore</code> attribute. </li>
+<LI>To disable {@code lint} checking for a specific Java class or method, use the <code>@SuppressLint</code>
+annotation. </LI>
+<li>To disable {@code lint} checking for specific sections of your XML file, use the
+<code>tools:ignore</code> attribute. </li>
</ul>
-<p>You can also specify your lint checking preferences for a specific Android project in the lint.xml file. For more information on configuring lint, see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
+<p>You can also specify your {@code lint} checking preferences for a specific Android project in
+the <code>lint.xml</code> file. For more information on configuring {@code lint}, see
+<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
diff --git a/docs/html/tools/help/sdk-manager.jd b/docs/html/tools/help/sdk-manager.jd
index b084237..0c77395 100644
--- a/docs/html/tools/help/sdk-manager.jd
+++ b/docs/html/tools/help/sdk-manager.jd
@@ -16,7 +16,7 @@
<li>On Windows, double-click the <code>SDK Manager.exe</code> file at the root of the Android
SDK directory.</li>
<li>On Mac or Linux, open a terminal and navigate to the <code>tools/</code> directory in the
-Android SDK, then execute <code>android sdk</code>.</li>
+location where the Android SDK is installed, then execute <code>android sdk</code>.</li>
</ul>
<p>You can select which packages you want to download by toggling the checkboxes on the left, then
diff --git a/docs/html/tools/projects/index.jd b/docs/html/tools/projects/index.jd
index 5f4f2cc..8665479 100644
--- a/docs/html/tools/projects/index.jd
+++ b/docs/html/tools/projects/index.jd
@@ -1,4 +1,6 @@
page.title=Managing Projects Overview
+meta.tags="project, mipmap"
+page.tags="project", "mipmap"
@jd:body
<div id="qv-wrapper">
@@ -8,7 +10,9 @@
<ol>
<li><a href="#ProjectFiles">Android Project Files</a></li>
<li><a href="#ApplicationModules">Android Application Modules</a></li>
-
+ <ol>
+ <li><a href="#mipmap">Managing Launcher Icons as mipmap Resources</a></li>
+ </ol>
<li><a href="#LibraryModules">Library Modules</a>
<ol>
<li><a href="#considerations">Development considerations</a></li>
@@ -230,7 +234,18 @@
focused). See the <a href=
"{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a> resource type.</dd>
- <dt><code>layout/</code></dt>
+
+ <dt><code>mipmap/</code></dt>
+
+ <dd>For app launcher icons. The Android system retains the resources in this folder
+ (and density-specific folders such as mipmap-xxxhdpi) regardless of the screen resolution
+ of the device where your app is installed. This behavior allows launcher apps to pick
+ the best resolution icon for your app to display on the home screen. For more information
+ about using the <code>mipmap</code> folders, see
+ <a href="#mipmap">Managing Launcher Icons as mipmap Resources</a>. </p>
+
+
+ <dt><code>layout/</code></dt>
<dd>XML files that are compiled into screen layouts (or part of a screen). See the <a href=
"{@docRoot}guide/topics/resources/layout-resource.html">Layout</a> resource type.</dd>
@@ -304,6 +319,46 @@
+<h2 id="mipmap">Managing Launcher Icons as mipmap Resources</h2>
+
+<p>Different home screen launcher apps on different devices show app launcher icons at various
+resolutions. When app resource optimization techniques remove resources for unused
+screen densities, launcher icons can wind up looking fuzzy because the launcher app has to upscale
+a lower-resolution icon for display. To avoid these display issues, apps should use the
+<code>mipmap/</code> resource folders for launcher icons. The Android system
+preserves these resources regardless of density stripping, and ensures that launcher apps can
+pick icons with the best resolution for display. </p>
+
+<p>Make sure launcher apps show a high-resolution icon for your app by moving all densities of your
+launcher icons to density-specific <code>res/mipmap/</code> folders
+(for example <code>res/mipmap-mdpi/</code> and <code>res/mipmap-xxxhdpi/</code>). The
+<code>mipmap/</code> folders replace the <code>drawable/</code> folders for launcher icons. For
+xxhpdi launcher icons, be sure to add the higher resolution xxxhdpi versions of the
+icons to enhance the visual experience of the icons on higher resolution devices.</p>
+
+<p class="note"><strong>Note:</strong> Even if you build a single APK for all devices, it is still
+best practice to move your launcher icons to the <code>mipmap/</code> folders.</p>
+
+
+<h3>Manifest update</h3>
+
+<p>When you move your launcher icons to the <code>mipmap-[density]</code> folders, change the
+launcher icon references in the <code>AndroidManifest.xml</code> file so your manifest references
+the <code>mipmap/</code> location. This example changes the manifest file to reference the
+<code>ic_launcher</code> icon in the <code>mipmap/</code> folder. </p>
+
+<pre>
+...
+<application android:name="ApplicationTitle"
+ android:label="@string/app_label"
+ android:icon="@mipmap/ic_launcher" >
+ ...
+</pre>
+
+
+
+
+
<h2 id="LibraryModules">Library Module</h2>
<div class="sidebox-wrapper">
diff --git a/docs/html/tools/revisions/gradle-plugin.jd b/docs/html/tools/revisions/gradle-plugin.jd
new file mode 100644
index 0000000..ebca5c7
--- /dev/null
+++ b/docs/html/tools/revisions/gradle-plugin.jd
@@ -0,0 +1,231 @@
+page.title=Android Plugin for Gradle Release Notes
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>See also</h2>
+ <ol>
+ <li><a href="{@docRoot}sdk/installing/studio-build.html">Build System Overview</a></li>
+ <li><a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin for Gradle</a></li>
+ </ol>
+
+</div>
+</div>
+
+
+<p>The Android build system uses the Android Plugin for Gradle to support building Android
+applications with the <a href="http://www.gradle.org/">Gradle</a> build toolkit. The plugin runs
+independent of Android Studio so the plugin and the Gradle build system can be updated
+independently of Android Studio.</p>
+
+<p class="note"><strong>Note:</strong> When you update Android Studio or open a project in a
+previous version of Android Studio, Android Studio prompts you to automatically update the plugin
+and Gradle to the latest available versions. You can choose to accept these updates based
+on your project's build requirements. </p>
+
+
+<h2 id="revisions">Revisions</h2>
+
+<p>The sections below provide notes about successive releases of
+the Android Plugin for Gradle, as denoted by revision number. To determine what revision of the
+plugin you are using, check the version declaration in the project-level
+<strong>build.gradle</strong> file. </p>
+
+<p>For a summary of known issues in Android Plugin for Gradle, see <a
+href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
+
+
+<div class="toggle-content opened">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Plugin for Gradle, Revision 1.1.0</a> <em>(February 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Gradle 2.2.1 or higher.</li>
+ <li>Build Tools 21.1.1 or higher.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Added new unit test support</li>
+ <ul>
+ <li>Enabled
+ <a href="{@docRoot}training/activity-testing/activity-unit-testing.html">unit tests</a> to
+ run on the local JVM against a special version of the <code>android.jar</code> file that is
+ compatible with popular mocking frameworks, for example Mockito. </li>
+ <li>Added new test tasks <code>testDebug</code>, <code>testRelease</code>, and
+ <code>testMyFlavorDebug</code> when using product flavors. </li>
+ <li>Added new source folders recognized as unit tests: <code>src/test/java/</code>,
+ <code>src/testDebug/java/</code>, <code>src/testMyFlavor/java/</code>.
+ <li>Added new configurations in the <code>build.gradle</code> file for declaring test-only
+ dependencies, for example, <code>testCompile 'junit:junit:4.11'</code>,
+ <code>testMyFlavorCompile 'some:library:1.0'</code>.
+ <p class="note"><strong>Note:</strong> Test-only dependencies are not currently compatible
+ with Jack (Java Android Compiler Kit). </p>
+ </li>
+ <li>Added the <code>android.testOptions.unitTests.returnDefaultValues</code> option to
+ control the behaviour of the mockable android.jar. </li>
+ </ul>
+ <li>Replaced <code>Test</code> in test task names with <code>AndroidTest</code>.
+ For example, the <code>assembleDebugTest</code> task is now
+ <code>assembleDebugAndroidTest</code> task. Unit test tasks still have <code>UnitTest</code>
+ in the task name, for example <code>assembleDebugUnitTest</code>. </li>
+ <li>Modified <a href="{@docRoot}tools/help/proguard.html">ProGuard</a> configuration files to
+ no longer apply to the test APK. If minification is enabled, ProGuard processes the test APK
+ and applies only the mapping file that is generated when minifying the main APK. </li>
+ <li>Updated dependency management</li>
+ <ul>
+ <li>Fixed issues using <code>provided</code> and <code>package</code> scopes.
+ <p class="note"><strong>Note:</strong> These scopes are incompatible with AAR
+ (Android ARchive) packages and will cause a build with AAR packages to fail.</p>
+ </li>
+ <li>Modified dependency resolution to compare the dependencies of an app under test and the
+ test app. If an artifact with the same version is found for both apps, it's not included with
+ the test app and is packaged only with the app under test. If an artifact with a different
+ version is found for both apps, the build fails.</li>
+ </ul>
+
+ <li>Added support for <code>anyDpi</code>
+ <a href="{@docRoot}guide/topics/resources/providing-resources.html"> resource qualifier</a>
+ in resource merger. </li>
+ <li>Improved evaluation and IDE sync speeds for projects with a large number of
+ Android <a href="{@docRoot}sdk/installing/create-project.html#CreatingAModule"> modules</a>. </li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
+ alt=""/>Android Plugin for Gradle, Revision 1.0.1</a> <em>(January 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Gradle 2.2.1 up to 2.3.x.
+ <p class="note"><strong>Note:</strong> This version of the Android Plugin for Gradle is
+ not compatible with Gradle 2.4 and higher. </p>
+ </li>
+ <li>Build Tools 21.1.1 or higher.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed issue with Gradle build failure when accessing the
+ <code>extractReleaseAnnotations</code> module.
+ (<a href="http://b.android.com/81638">Issue 81638</a>).</li>
+ <li>Fixed issue with <code>Disable</code> passing the
+ <code>--no-optimize</code> setting to the Dalvik Executable (dex) bytecode.
+ (<a href="http://b.android.com/82662">Issue 82662</a>).</li>
+ <li>Fixed manifest merger issues when importing libraries with a
+ <code>targetSdkVersion</code> less than 16.</li>
+ <li>Fixed density ordering issue when using Android Studio with JDK 8.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
+ alt=""/>Android Plugin for Gradle, Revision 1.0.0</a> <em>(December 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Gradle 2.2.1 up to 2.3.x.
+ <p class="note"><strong>Note:</strong> This version of the Android Plugin for Gradle is
+ not compatible with Gradle 2.4 and higher. </p>
+ </li>
+ <li>Build Tools 21.1.1 or higher.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Initial plugin release.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+
+
+
+<h2>Updating the Android Plugin for Gradle Version</h2>
+<p>The Android Plugin for Gradle version is specified in the
+<strong>File > Project Structure</strong> menu or the project-level
+<code>build.gradle</code> file. The plugin version applies to all modules built in that
+Android Studio project. This example updates the Android Plugin for Gradle to version 1.1:
+<pre>
+...
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.1'
+ }
+...
+</pre>
+
+
+<p class="caution"><strong>Caution:</strong> You should not use dynamic dependencies (+) in
+version numbers. Using this feature can cause unexpected version updates and difficulty
+resolving version differences.
+</p>
+
+<p>If you're building with Gradle but using not Android Studio, the build process downloads the
+latest Android Plugin for Gradle plugin when it runs. </p>
+
+
+
+<h2>Updating the Gradle Version </h2>
+
+<p>Android Studio requires Gradle version 2.2.1 or later. To view and
+update the Gradle version, edit the Gradle distribution reference in the
+<code>gradle/wrapper/gradle-wrapper.properties</code> file. This example shows the
+Android Plugin for Gradle version set to 2.2.1.</p>
+
+<pre>
+...
+distributionUrl=http\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+...
+</pre>
+
+
+
+
+<p>For more details about the supported Android Plugin for Gradle properties and syntax, click
+the link to the
+<a href="{@docRoot}tools/building/plugin-for-gradle.html">Plugin Language Reference</a>.</p>
+
+
+
+
+
diff --git a/docs/html/tools/revisions/studio.jd b/docs/html/tools/revisions/studio.jd
index 3806933..af25d9c 100644
--- a/docs/html/tools/revisions/studio.jd
+++ b/docs/html/tools/revisions/studio.jd
@@ -29,7 +29,7 @@
<p>For an introduction to Android Studio, read the
<a href="{@docRoot}tools/studio/index.html">Android Studio</a> guide.</p>
-<p>Periodic updates are pushed to Android Studio without requiring you to update from here. To
+<p>Periodic updates are pushed to Android Studio without requiring you to update. To
manually check for updates, select <strong>Help > Check for updates</strong> (on Mac, select
<strong>Android Studio > Check for updates</strong>).</p>
@@ -43,6 +43,33 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Studio v1.1</a> <em>(February 2015)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+ <p>Various fixes and enhancements:</p>
+ <ul>
+ <li>Added support for the <a href="{@docRoot}design/wear/index.html">Android Wear</a> watch
+ template. </li>
+ <li>Modified new project and module creation to include
+ <a href="{@docRoot}tools/projects/index.html#mipmap"><code>res/mipmap</code></a> folders for
+ density-specific launcher icons. These <code>res/mipmap</code> folders replace the
+ <a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>res/drawable</code></a>
+ folders for launcher icons. </li>
+ <li>Updated launcher icons to have a
+ <a href="{@docRoot}design/material/index.html">Material Design</a> look and added an
+ <code>xxxhdpi</code> launcher icon. </li>
+ <li>Added and enhanced <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a> checks
+ for region and language combinations, launcher icons, resource names, and other common
+ code problems.</li>
+ <li>Added support for Best Current Practice (BCP) language tag 47. </li>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Android Studio v1.0.1</a> <em>(December 2014)</em>
</p>
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index 9f24008..1860feb 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -10,6 +10,7 @@
<li><a href="#build-system">Android Build System</a></li>
<li><a href="#debug-perf">Debug and Performance</a></li>
<li><a href="#install-updates">Installation, Setup, and Update Management</a></li>
+ <li><a href="#proxy">HTTP Proxy Settings</a></li>
<li><a href="#other">Other Highlights</a></li>
@@ -35,7 +36,7 @@
<li>Build variants and multiple <code>apk</code> file generation</li>
<li>Code templates to help you build common app features</li>
<li>Rich layout editor with support for drag and drop theme editing</li>
- <li>Lint tools to catch performance, usability, version compatibility, and other problems</li>
+ <li>{@code lint} tools to catch performance, usability, version compatibility, and other problems</li>
<li>ProGuard and app-signing capabilities</li>
<li>Built-in support for <a
href="http://developers.google.com/cloud/devtools/android_studio_templates/"
@@ -64,8 +65,8 @@
<h3 id="project-view"><em>Android</em> Project View</h3>
<p>By default, Android Studio displays your profile files in the <em>Android</em> project view. This
view shows a flattened version of your project's structure that provides quick access to the key
-source files of Android projects and helps you work with the new
-<a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>.
+source files of Android projects and helps you work with the
+<a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>.
The Android project view:</p>
<ul>
@@ -95,13 +96,12 @@
<p>For example, <em>Android</em> project view groups all the instances of the
<code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
-<p class="note"><strong>Note:</strong> The project structure on disk differs from this flattened
-representation. To switch to back the segregated project view, select <strong>Project</strong> from
-the <strong>Project</strong drop-down. </p>
+<p class="note"><strong>Note:</strong> The project structure on disk differs from this flattened
+representation. To switch to back to the segregated project view, select <strong>Project</strong> from
+the <strong>Project</strong> drop-down. </p>
-
-<h3>New Project and Directory Structure</h3>
+<h3>Android Studio Project and Directory Structure</h3>
<p>When you use the <em>Project</em> view of a new project in Android Studio, you
should notice that the project structure appears different than you may be used to in Eclipse. Each
instance of Android Studio contains a project with one or more application modules. Each
@@ -119,6 +119,7 @@
<a href="{@docRoot}tools/projects/index.html">Managing Projects</a>.</p>
+
<h3>Creating new files</h3>
<p>You can quickly add new code and resource files by clicking the appropriate directory in the
<strong>Project</strong> pane and pressing <code>ALT + INSERT</code> on Windows and Linux or
@@ -180,7 +181,7 @@
<p class="note"><strong>Note:</strong> The <em>applicationId</em> is specified only in your
build.gradle file, and not in the AndroidManifest.xml file.</p>
-<p>When using build variants, the build system enables you to to uniquely identify different
+<p>When using build variants, the build system enables you to uniquely identify different
packages for each product flavors and build types. The application ID in the build type is added as
a suffix to those specified for the product flavors. </p>
@@ -242,19 +243,28 @@
-<h3> Memory Monitor</h3>
+<h3>Memory Monitor</h3>
<p>Android Studio provides a memory monitor view so you can more easily monitor your
app's memory usage to find deallocated objects, locate memory leaks and track the amount of
memory the connected device is using. With your app running on a device or emulator, click the
<strong>Memory Monitor</strong> tab in the lower right corner to launch the memory monitor. </p>
<img src="{@docRoot}images/tools/studio-memory-monitor.png" />
- <p class="img-caption"><strong>Figure 4.</strong> Memory Monitor</p>
+ <p class="img-caption"><strong>Figure 5.</strong> Memory Monitor</p>
-<h3> New Lint inspections</h3>
-<p>Lint has several new checks to ensure:
+<h3>Code Inspections</h3>
+<p>In Android Studio, the configured <a href="{@docRoot}tools/help/lint.html"><code>lint</code></a> and
+other IDE inspections run automatically whenever you compile your program. In addition to the
+configured {@code lint} checks, additional
+<a href="https://www.jetbrains.com/idea/help/inspection-basics.html?search=inspection" class="external-link"
+target="_blank">IntelliJ code inspections</a>
+run to streamline code review.</p>
+
+
+<p>Android Studio enables several <code>lint</code> checks
+to ensure:
<ul>
<li><code> Cipher.getInstance()</code> is used with safe values</li>
<li>In custom Views, the associated declare-styleable for the custom view uses the same
@@ -267,44 +277,75 @@
<li>many others</li>
</ul>
-<p>Hovering over a Lint error displays the full issue explanation inline for easy error
+
+<p>Hovering over an inspection error displays the full issue explanation inline for easy error
resolution. There is also a helpful hyperlink at the end of the error message for additional
error information.</p>
-<p>With Android Studio, you can run Lint for a specific build variant, or for all build variants.
-You can configure Lint by adding a <em>lintOptions</em> property to the Android settings in the
-build.gradle file. </p>
+<p>With Android Studio, you can also run {@code lint} inspections for a specific build variant, or
+for all build variants. You can configure the {@code lint} inspections that run by adding a
+<code>lintOptions</code> property to the Android settings in the <code>build.gradle</code>
+file. </p>
- <pre>
- android {
- lintOptions {
- // set to true to turn off analysis progress reporting by lint
- quiet true
- // if true, stop the gradle build if errors are found
- abortOnError false
- // if true, only report errors
- ignoreWarnings true
- </pre>
+<pre>
+android {
+ lintOptions {
+ // set to true to turn off analysis progress reporting by lint
+ quiet true
+ // if true, stop the gradle build if errors are found
+ abortOnError false
+ // if true, only report errors
+ ignoreWarnings true
+ }
+</pre>
+
+
+<p>You can also manage inspection profiles and configure inspections within Android Studio.
+Choose <strong>File > Settings > Project Settings</strong>. The
+<em>Inspection Configuration</em> page appears with the supported inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 5.</strong> Inspection Configuration</p>
+
+<p class="note"><strong>Note:</strong> If you wish to change the behavior of specific
+inspection notifications, you can change the inspection severity, for example from <em>warning</em>
+to <em>error</em>. </p>
+
+
+<p>To manually run inspections in Android Studio, choose <strong>Analyze > Inspect Code</strong>.
+The <em>Inspections Scope</em> dialog appears so you can specify the desired inspection profile and scope.</p>
+
+
+
+<h4>Running Inspections from the command line</h4>
+<p>You can also run {@code lint} inspections from the command line in your SDK directory. </p>
+<pre>
+sdk$ lint [flags] <project directories>
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code lint} <strong>--show</strong> and <strong>--list</strong>
+flags can be used to display the available issues and explanations. </p>
+
<p>For more information, see
-<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with Lint</a>.</p>
+<a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with {@code lint}</a> and
+<a href="{@docRoot}tools/help/lint.html">lint tool</a>.</p>
<h3>Dynamic layout preview</h3>
<p>Android Studio allows you to work with layouts in both a <em>Design View</em> </p>
<p><img src="{@docRoot}images/tools/studio-helloworld-design.png" alt="" />
</p>
- <p class="img-caption"><strong>Figure 5.</strong> Hello World App with Design View</p>
+ <p class="img-caption"><strong>Figure 6.</strong> Hello World App with Design View</p>
<p>and a <em>Text View</em>. </p>
<p><img src="{@docRoot}images/tools/studio-helloworld-text.png" alt="" />
- <pclass="img-caption"><strong>Figure 6.</strong> Hello World App with Text View</p>
+ <pclass="img-caption"><strong>Figure 7.</strong> Hello World App with Text View</p>
<p>Easily select and preview layout changes for different device images, display
densities, UI modes, locales, and Android versions (multi-API version rendering).
<p><img src="{@docRoot}images/tools/studio-api-version-rendering.png" /></p>
- <p class="img-caption"><strong>Figure 7.</strong> API Version Rendering</p>
+ <p class="img-caption"><strong>Figure 8.</strong> API Version Rendering</p>
<p>From the Design View, you can drag and drop elements from the Palette to the Preview or
@@ -341,18 +382,19 @@
an optimized default Android Virtual Device (AVD) based on Android 5 (Lollipop) for speedy and
reliable emulation. </p>
<p><img src="{@docRoot}images/tools/studio-setup-wizard.png" /></p>
-<p class="img-caption"><strong>Figure 8.</strong> Setup Wizard</p>
+<p class="img-caption"><strong>Figure 9.</strong> Setup Wizard</p>
<h3>Expanded template and form factor support</h3>
-<p>Android Studio supports new templates for Google Services and expands the available device
+<p>Android Studio supports templates for Google Services and expands the available device
types. </p>
<h4> Android Wear and TV support</h4>
<p>For easy cross-platform development, the Project Wizard provides new templates for
creating your apps for Android Wear and TV. </p>
<p><img src="{@docRoot}images/tools/studio-tvwearsupport.png" />
- <p class="img-caption"><strong>Figure 9.</strong> New Form Factors</p>
+
+ <p class="img-caption"><strong>Figure 10.</strong> Supported Form Factors</p>
<p>During app creation, the Project Wizard also displays an API Level dialog to help you choose
the best <em>minSdkVersion</em> for your project.</p>
@@ -362,7 +404,7 @@
and create a cloud end-point is as easy as selecting <em>File > New Module > App Engine Java
Servlet Module</em> and specifying the module, package, and client names. </p>
<p><img src="{@docRoot}images/tools/studio-cloudmodule.png" /></p>
- <p class="img-caption"><strong>Figure 10.</strong> Setup Wizard</p>
+ <p class="img-caption"><strong>Figure 11.</strong> Setup Wizard</p>
@@ -386,6 +428,120 @@
+<h2 id="proxy">Proxy Settings</h2>
+<p>Proxies serve as intermediary connection points between HTTP clients and web servers that add
+security and privacy to internet connections.</p>
+
+<p>To support running Android Studio behind a firewall, set the proxy settings for the
+Android Studio IDE and the SDK Manager. Use the Android Studio IDE HTTP Proxy settings page to set
+the HTTP proxy settings for Android Studio. The SDK Manager has a separate HTTP Proxy settings
+page.</p>
+
+<p>When running the Android Plugin for Gradle from the command line or on machines where
+Android Studio is not installed, such as continuous integration servers, set the proxy settings
+in the Gradle build file.</p>
+
+<p class="note"><strong>Note:</strong> After the initial installation of the Android Studio bundle,
+Android Studio can run with internet access or off-line. However, Android Studio requires an
+internet connection for Setup Wizard synchronization, 3rd-party library access, access to remote
+repositories, Gradle initialization and synchronization, and Android Studio version updates.</p>
+
+
+<h3>Setting up the Android Studio Proxy</h3>
+<p>Android Studio supports HTTP proxy settings so you can run Android Studio behind a firewall or
+secure network. To set the HTTP proxy settings in Android Studio:</p>
+<ol>
+ <li>From the main menu choose <strong>File > Settings > IDE Setting -- HTTP Proxy</strong>.
+
+<li>In Android Studio, open the IDE Settings dialog.
+ <ul>
+ <li>On Windows and Linux, choose
+ <strong>File > Settings > IDE Setting -- HTTP Proxy</strong>. </li>
+ <li>On Mac, choose
+ <strong>Android Studio > Preferences > IDE Setting -- HTTP Proxy</strong>. </li>
+ </ul>
+ The HTTP Proxy page appears.</li>
+ <li>Select <strong>auto-detection</strong> to use an auto-configuration URL to configure the
+ proxy settings or <strong>manual</strong> to enter each of the settings. For a detailed explanation
+ of these settings, see
+ <a href="https://www.jetbrains.com/idea/help/http-proxy.html">HTTP Proxy</a>. </li>
+ <li>Click <strong>Apply</strong> to enable the proxy settings. </li>
+</ol>
+
+<h3>Android Plugin for Gradle HTTP proxy settings</h3>
+When running the Android Plugin from the command line or on machines where Android Studio is not
+installed, set the Android Plugin for Gradle proxy settings in the Gradle build file.</p>
+
+<p>For application-specific HTTP proxy settings, set the proxy settings in the
+<strong>build.gradle</strong> file as required for each application module.</p>
+<pre>
+apply plugin: 'com.android.application'
+
+android {
+ ...
+
+ defaultConfig {
+ ...
+ systemProp.http.proxyHost=proxy.company.com
+ systemProp.http.proxyPort=443
+ systemProp.http.proxyUser=userid
+ systemProp.http.proxyPassword=password
+ systemProp.http.auth.ntlm.domain=domain
+ }
+ ...
+}
+</pre>
+
+
+
+<p>For project-wide HTTP proxy settings, set the proxy settings in the
+<code>gradle/gradle.properties</code> file. </p>
+
+<pre>
+# Project-wide Gradle settings.
+...
+
+systemProp.http.proxyHost=proxy.company.com
+systemProp.http.proxyPort=443
+systemProp.http.proxyUser=username
+systemProp.http.proxyPassword=password
+systemProp.http.auth.ntlm.domain=domain
+
+systemProp.https.proxyHost=proxy.company.com
+systemProp.https.proxyPort=443
+systemProp.https.proxyUser=username
+systemProp.https.proxyPassword=password
+systemProp.https.auth.ntlm.domain=domain
+
+...
+</pre>
+
+
+<p>For information about using Gradle properties for proxy settings, see the
+ <a href="http://www.gradle.org/docs/current/userguide/build_environment.html">Gradle User Guide</a>.</p>
+
+<p class="note"><strong>Note:</strong> When using Android Studio, the settings in the Android
+Studio IDE HTTP proxy settings page override the HTTP proxy settings in the
+<strong>gradle.properties</strong> file.</p>
+
+
+
+<h3>SDK Manager HTTP Proxy Settings </h3>
+<p>SDK Manager proxy settings enable proxy internet access for Android package and library
+updates from SDK Manager packages. </p>
+
+<p>To set the SDK Manager settings for proxy internet access, start the SDK Manager and open the
+SDK Manager page. </p>
+
+<ul>
+ <li>On Windows, select <strong>Tools > Options</strong> from the menu bar. </li>
+ <li>On Mac and Linux, choose <strong>Tools > Options</strong> from the system menu bar. </li>
+ </ul>
+
+<p>The Android SDK Manager page appears. Enter the settings and click <strong>Apply</strong>. </p>
+
+
+
<h2 id="other">Other Highlights</h2>
<h3> Translation Editor</h3>
@@ -399,24 +555,25 @@
<strong>Open Editor</strong> link. </p>
<img src="{@docRoot}images/tools/studio-translationeditoropen.png" />
- <p class="img-caption"><strong>Figure 11.</strong> Translation Editor</p>
+ <p class="img-caption"><strong>Figure 12.</strong> Translation Editor</p>
<h3> Editor support for the latest Android APIs</h3>
-<p>Android Studio supports the new
+<p>Android Studio supports the
<a href="{@docRoot}design/material/index.html">Material Design</a></li> themes, widgets, and
graphics, such as shadow layers and API version rendering (showing the layout across different
-UI versions). Also, the new drawable XML tags and attributes, such as <ripple>
+UI versions). Also, the drawable XML tags and attributes, such as <ripple>
and <animated-selector>, are supported.</p>
<h3 id="git-samples"> Easy access to Android code samples on GitHub</h3>
-<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or Welcome page
+<p>Clicking <strong>Import Samples</strong> from the <strong>File</strong> menu or <em>Welcome</em> page
+
provides seamless access to Google code samples on GitHub.</p>
<p><img src="{@docRoot}images/tools/studio-samples-githubaccess.png" /></p>
- <p class="img-caption"><strong>Figure 12.</strong> Code Sample Access</p>
+ <p class="img-caption"><strong>Figure 13.</strong> Code Sample Access</p>
<p><img src="{@docRoot}images/tools/studio-sample-in-editor.png" /></p>
- <p class="img-caption"><strong>Figure 13.</strong> Imported Code Sample</p>
+ <p class="img-caption"><strong>Figure 14.</strong> Imported Code Sample</p>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 073e81c..fa6328e 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -249,6 +249,9 @@
<li><a href="<?cs var:toroot ?>tools/revisions/build-tools.html">
<span class="en">SDK Build Tools</span>
</a></li>
+ <li><a href="<?cs var:toroot ?>tools/revisions/gradle-plugin.html">
+ <span class="en">Android Plugin for Gradle</span>
+ </a></li>
<li><a href="<?cs var:toroot ?>tools/revisions/platforms.html">
<span class="en">SDK Platforms</span></a></li>
<li><a href="<?cs var:toroot ?>tools/sdk/eclipse-adt.html">
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 71b93c0..79268a0 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -103,10 +103,13 @@
Activities</a> for more information.</p>
</div>
</div>
- <li>Under <strong>Add an activity to your project</strong>, select <strong>Blank Activity</strong>
- and click <strong>Next</strong>.</li>
- <li>Under <strong>Describe the new activity for your project</strong>, leave the fields as they
- are and click <strong>Finish</strong>.</li>
+ <li>Under <strong>Add an activity to <<em>template</em>></strong>, select <strong>Blank
+ Activity</strong> and click <strong>Next</strong>.</li>
+ <li>Under <strong>Choose options for your new file</strong>, change the
+ <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout Name</strong> changes
+ to <em>activity_my</em>, and the <strong>Title</strong> to <em>MyActivity</em>. The
+ <strong>Menu Resource Name</strong> is <em>menu_my</em>.
+ <li>Click the <strong>Finish</strong> button to create the project.</li>
</ol>
<p>Your Android project is now a basic "Hello World" app that contains some default files. Take a
@@ -123,7 +126,7 @@
select the file you see the class definition for the activity you created. When you build and
run the app, the {@link android.app.Activity} class starts the activity and loads the layout file
that says "Hello World!"</dd>
- <dt><code>app/src/res/AndroidManifest.xml</code></dt>
+ <dt><code>app/src/main/AndroidManifest.xml</code></dt>
<dd>The <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a> describes
the fundamental characteristics of the app and defines each of its components. You'll revisit
this file as you follow these lessons and add more components to your app.</dd>
@@ -159,13 +162,16 @@
<p>Note also the <code>/res</code> subdirectories that contain the
<a href="{@docRoot}guide/topics/resources/overview.html">resources</a> for your application:</p>
<dl>
- <dt><code>drawable-hdpi/</code></dt>
- <dd>Directory for drawable objects (such as bitmaps) that are designed for high-density
- (hdpi) screens. Other drawable directories contain assets designed for other screen densities.
+ <dt><code>drawable<em><density></em>/</code></dt>
+ <dd>Directories for drawable objects (such as bitmaps) that are designed for various densities,
+ such as medium-density (mdpi) and high-density (hdpi) screens. Other drawable directories
+ contain assets designed for other screen densities.
Here you'll find the ic_launcher.png that appears when you run the default app.</dd>
<dt><code>layout/</code></dt>
<dd>Directory for files that define your app's user interface like activity_my.xml,
discussed above, which describes a basic layout for the MyActivity class.</dd>
+ <dt><code>menu/</code></dt>
+ <dd>Directory for files that define your app's menu items.</dd>
<dt><code>values/</code></dt>
<dd>Directory for other XML files that contain a collection of resources, such as
string and color definitions. The strings.xml file defines the "Hello world!" string that
@@ -180,9 +186,9 @@
using the SDK tools from a command line:</p>
<ol>
- <li>Change directories into the Android SDK’s <code>tools/</code> path.</li>
+ <li>Change directories into the Android SDK’s <code>sdk/</code> path.</li>
<li>Execute:
-<pre class="no-pretty-print">android list targets</pre>
+<pre class="no-pretty-print">tools/android list targets</pre>
<p>This prints a list of the available Android platforms that you’ve downloaded for your SDK. Find
the platform against which you want to compile your app. Make a note of the target ID. We
recommend that you select the highest version possible. You can still build your app to
@@ -212,4 +218,3 @@
-
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index c09669f..fdf0d1f 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -83,14 +83,37 @@
<h3>Run the app from a command line</h3>
-<ol>
- <li>Change directories to the root of your Android project and execute:
-<pre class="no-pretty-print">ant debug</pre></li>
- <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
-<code>PATH</code> environment variable, then execute:
-<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
- <li>On your device, locate <em>MyFirstApp</em> and open it.</li>
-</ol>
+<p>Open a command-line and navigate to the root of your project directory.
+ Use Gradle to build your project in debug mode, invoke the <code>assembleDebug</code> build task
+ using the Gradle wrapper script (<code>gradlew assembleRelease</code>).
+
+ <p>This creates your debug <code>.apk</code> file inside the module <code>build/</code>
+ directory, named <code>MyFirstApp-debug.apk</code>. </p>
+
+ <p>On Windows platforms, type this command:</p>
+
+<pre>
+> gradlew.bat assembleDebug
+</pre>
+
+<p>On Mac OS and Linux platforms, type these commands:</p>
+
+<pre>
+$ chmod +x gradlew
+$ ./gradlew assembleDebug
+</pre>
+
+ <p>After you build the project, the output APK for the app module is located in
+ <code>app/build/outputs/apk/</code>
+
+ <p class="note"><strong>Note:</strong> The first command (<code>chmod</code>) adds the execution
+ permission to the Gradle wrapper script and is only necessary the first time you build this
+ project from the command line.</p>
+
+ <p>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
+ <code>PATH</code> environment variable, then execute:
+ <pre class="no-pretty-print">adb install app/build/outputs/MyFirstApp-debug.apk</pre><p>
+ <p>On your device, locate <em>MyFirstApp</em> and open it.</p>
<p>That's how you build and run your Android app on a device!
To start developing, continue to the <a href="building-ui.html">next
@@ -114,12 +137,29 @@
<ol>
<li>Launch the Android Virtual Device Manager:
<ul>
- <li>In the Android Studio tool bar, click the Android Virtual Device Manager icon
- <img src="{@docRoot}images/tools/avd-manager-studio.png"
- style="vertical-align:baseline;margin:0; max-height:1em" />.</li>
- <li>From the command line, change directories to <code><sdk>/tools/</code> and execute:
- <pre class="no-pretty-print">android avd</pre></li>
+ <li>In Android Studio, select <strong>Tools > Android > AVD Manager</strong>, or click
+ the AVD Manager icon <img src="{@docRoot}images/tools/avd-manager-studio.png" style="vertical-align:bottom;margin:0;height:19px"> in the toolbar.</li>
+ <li>Or, from the command line, change directories to
+ <code>sdk/</code> and execute:
+ <pre class="no-pretty-print">tools/android avd</pre>
+ <p class="note"><strong>Note:</strong> The AVD Manager that appears
+ when launched from the command line is different from the version in
+ Android Studio, so the following instructions may not all apply.</p>
+ </li>
</ul>
+
+ <img src="{@docRoot}images/studio-avdmgr-firstscreen.png" alt=""
+ style="margin-top:1em">
+ <p class="img-caption"><strong>Figure 1.</strong> The AVD Manager main screen shows your current virtual devices.</p>
+
+ </li>
+ <li>On the AVD Manager main screen (figure 1), click <strong>Create Virtual Device</strong>.</li>
+ <li>In the Select Hardware window, select a device configuration, such as Nexus 6,
+ then click <strong>Next</strong>.
+ </li>
+ <li>Select the desired system version for the AVD and click <strong>Next</strong>.
+ </li>
+ <li>Verify the configuration settings, then click <strong>Finish</strong>.
</li>
<li>In the <strong>Android Virtual Device Manager</strong> window, click <strong>Create</strong>.</li>
<li>Enter an <strong>AVD Name</strong>.</li>
@@ -137,40 +177,33 @@
<h3>Run the app from Android Studio</h3>
<ol>
<li>In <strong>Android Studio</strong>, select your project and click <strong>Run</strong>
- <img src="{@docRoot}images/tools/as-run.png" style="vertical-align:baseline;margin:0; max-height:1em" />
- from the toolbar.</li>
+ <img src="{@docRoot}images/tools/as-run.png" style="vertical-align:baseline;margin:0; max-height:1em" /> from the toolbar.</li>
<li>In the <strong>Choose Device</strong> window, click the <strong>Launch emulator</strong> radio
button.</li>
<li>From the <strong>Android virtual device</strong> pull-down menu, select the emulator
you created, and click <strong>OK</strong>.</li>
</ol>
<p>It can take a few minutes for the emulator to load itself. You may have to unlock the screen.
- When you do, My First App appears on the emulator screen.</p>
+When you do, <em>My First App</em> appears on the emulator screen.</p>
<h3>Run your app from the command line</h3>
-
-<ol>
- <li>Change directories to the root of your Android project and execute:
- <pre class="no-pretty-print">ant debug</pre></li>
+ <ol>
+ <li>Build the project from the command line. The output APK for the app module is located in
+ <code>app/build/outputs/apk/</code>.</li>
<li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
- <code>PATH</code> environment variable, then execute:
- <pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
+ <code>PATH</code> environment variable.</li>
+ <li>Execute this command:
+ <p>
+ <pre class="no-pretty-print">adb install app/build/outputs/MyFirstApp-debug.apk</pre>
+ </p>
+ </li>
<li>On the emulator, locate <em>MyFirstApp</em> and open it.</li>
-</ol>
+ </ol>
-<p>That's how you build and run your Android app on the emulator!
+ <p>That's how you build and run your Android app on the emulator!
To start developing, continue to the <a href="building-ui.html">next
-lesson</a>.</p>
-
-
-
-
-
-
-
-
-
+ lesson</a>.</p>
diff --git a/docs/html/training/basics/fragments/support-lib.jd b/docs/html/training/basics/fragments/support-lib.jd
deleted file mode 100644
index a1d781b..0000000
--- a/docs/html/training/basics/fragments/support-lib.jd
+++ /dev/null
@@ -1,83 +0,0 @@
-page.title=Using the Support Library
-page.tags=support library
-helpoutsWidget=true
-
-trainingnavtop=true
-
-@jd:body
-
-<div id="tb-wrapper">
- <div id="tb">
- <h2>This lesson teaches you to</h2>
- <ol>
- <li><a href="#Setup">Set Up Your Project with the Support Library</a></li>
- <li><a href="#Apis">Import the Support Library APIs</a></li>
- </ol>
- <h2>You should also read</h2>
- <ul>
- <li><a href="{@docRoot}tools/support-library/index.html">Support Library</a></li>
- </ul>
- </div>
-</div>
-
-<p>The Android <a href="{@docRoot}tools/support-library/index.html">Support Library</a> provides a JAR
-file with an API library that allows you to use some of the more recent Android APIs in your app
-while running on earlier versions of Android. For instance, the Support Library provides a version
-of the {@link android.app.Fragment} APIs that you can use on Android 1.6 (API level 4) and
-higher.</p>
-
-<p>This lesson shows how to set up your app to use the Support Library in order to use fragments
-to build a dynamic app UI.</p>
-
-
-<h2 id="Setup">Set Up Your Project with the Support Library</h2>
-
-<div class="figure" style="width:527px">
-<img src="{@docRoot}images/training/basics/sdk-manager.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> The Android SDK Manager with the
-Android Support package selected.</p>
-</div>
-
-<p>To set up your project:</p>
-
-<ol>
- <li>Download the Android Support package using the SDK Manager.</li>
-
- <li>Create a <code>libs</code> directory at the top level of your Android project.</li>
- <li>Locate the JAR file for the library you want to use and copy it into the <code>libs/</code>
-directory.
-<p>For example, the library that supports API level 4 and up is located at
-<code><sdk>/extras/android/support/v4/android-support-v4.jar</code>.</p></li>
- <li>Update your manifest file to set the minimum API level to <code>4</code> and the target
-API level to the latest release:
- <pre><uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" /></pre>
- </li>
-</ol>
-
-
-<h2 id="Apis">Import the Support Library APIs</h2>
-
-<p>The Support Library includes a variety of APIs that were either added in recent versions of
-Android or don't exist in the platform at all and merely provide additional support to you when
-developing specific application features.</p>
-
-<p>You can find all the API reference documentation for the Support Library in the
-platform docs at {@link android.support.v4.app android.support.v4.*}.</p>
-
-<div class="warning"><p><strong>Warning:</strong> To be sure that you don't accidentally use new
-APIs on an older system version, be certain that you import the {@link
-android.support.v4.app.Fragment} class and related APIs from the {@link android.support.v4.app}
-package:</p>
-<pre>
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-...
-</pre>
-</div>
-
-
-<p>When creating an activity that hosts fragments while using the Support Library, you must also
-extend the {@link android.support.v4.app.FragmentActivity} class instead of the traditional {@link
-android.app.Activity} class. You'll see sample code for the fragment and activity in the next
-lesson.</p>
-
diff --git a/docs/html/training/enterprise/app-compatibility.jd b/docs/html/training/enterprise/app-compatibility.jd
index 1ae1ee3..216a799 100644
--- a/docs/html/training/enterprise/app-compatibility.jd
+++ b/docs/html/training/enterprise/app-compatibility.jd
@@ -1,4 +1,6 @@
page.title=Ensuring Compatibility with Managed Profiles
+page.metaDescription=Learn how to make sure your apps operate smoothly in a corporate environment by following some best practices.
+
@jd:body
<div id="tb-wrapper">
diff --git a/docs/html/training/enterprise/app-restrictions.jd b/docs/html/training/enterprise/app-restrictions.jd
new file mode 100644
index 0000000..fc5dfcc
--- /dev/null
+++ b/docs/html/training/enterprise/app-restrictions.jd
@@ -0,0 +1,351 @@
+page.title=Implementing App Restrictions
+page.metaDescription=Learn how to implement app restrictions and configuration settings that can be changed by other apps on the same device.
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#define_restrictions">Define App Restrictions</a></li>
+ <li><a href="#check_restrictions">Check App Restrictions</a></li>
+ <li><a href="#listen">Listen for App Restriction Changes</a></li>
+</ol>
+
+<!-- related docs (NOT javadocs) -->
+<h2>Resources</h2>
+<ul>
+ <li><a href="{@docRoot}samples/AppRestrictionSchema/index.html">AppRestrictionSchema</a>
+ sample app</li>
+ <li><a href="{@docRoot}samples/AppRestrictionEnforcer/index.html">AppRestrictionEnforcer</a>
+ sample app</li>
+</ul>
+
+</div>
+</div>
+
+<p>If you are developing apps for the enterprise market, you may need to satisfy
+particular requirements set by a company's policies. Application restrictions
+allow the enterprise administrator to remotely specify settings for apps.
+This capability is particularly useful for enterprise-approved apps deployed to
+a managed profile.</p>
+
+<p>For example, an enterprise might require that approved apps allow the
+enterprise administrator to:</p>
+
+<ul>
+ <li>Whitelist or blacklist URLs for a web browser</li>
+ <li>Configure whether an app is allowed to sync content via cellular, or just
+ by Wi-Fi</li>
+ <li>Configure the app's email settings</li>
+</ul>
+
+<p>
+ This guide shows how to implement these configuration settings in your app.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> For historical reasons, these configuration settings are known as
+ <em>restrictions,</em> and are implemented with files and classes that use this
+ term (such as {@link android.content.RestrictionsManager}). However, these
+ restrictions can actually implement a wide range of configuration options,
+ not just restrictions on app functionality.
+</p>
+
+<h2 id="overview">
+ Remote Configuration Overview
+</h2>
+
+<p>
+ Apps define the restrictions and configuration options that can be remotely
+ set by an administrator. These restrictions are
+ arbitrary configuration settings that can be changed by a restrictions
+ provider. If your app is running on an enterprise device's managed
+ profile, the enterprise administrator can change your app's restrictions.
+</p>
+
+<p>
+ The restrictions provider is another app running on the same device.
+ This app is typically controlled by the enterprise administrator. The
+ enterprise administrator communicates restriction changes to the restrictions
+ provider app. That app, in turn, changes the restrictions on your app.
+</p>
+
+<p>
+ To provide externally configurable restrictions:
+</p>
+
+<ul>
+ <li>Declare the restrictions in your app manifest. Doing so allows the
+ enterprise administrator to read the app's restrictions through Google
+ Play APIs.
+ </li>
+
+ <li>Whenever the app resumes, use the {@link
+ android.content.RestrictionsManager} object to check the current
+ restrictions, and change your app's UI and behavior to conform with those
+ restrictions.
+ </li>
+
+ <li>Listen for the
+ {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
+ ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. When you receive this
+ broadcast, check the {@link android.content.RestrictionsManager} to see what
+ the current restrictions are, and make any necessary changes to your app's
+ behavior.
+ </li>
+</ul>
+
+<h2 id="define_restrictions">
+ Define App Restrictions
+</h2>
+
+<p>
+ Your app can support any restrictions you want to define. You declare the
+ app's restrictions in a <em>restrictions file</em>, and declare the
+ restrictions file in the manifest. Creating a restrictions file allows other
+ apps to examine the restrictions your app provides. Enterprise Mobility
+ Management (EMM) partners can read your app's restrictions by using Google
+ Play APIs.
+</p>
+
+<p>
+ To define your app's remote configuration options, put the following element
+ in your manifest's
+ <a href="{@docRoot}guide/topics/manifest/application-element.html">
+ <code><application></code></a> element:
+</p>
+
+<pre><meta-data android:name="android.content.APP_RESTRICTIONS"
+ android:resource="@xml/app_restrictions" />
+</pre>
+
+<p>
+ Create a file named <code>app_restrictions.xml</code> in your app's
+ <code>res/xml</code> directory. The structure of that file is described in
+ the reference for {@link android.content.RestrictionsManager}. The file has a
+ single top-level <code><restrictions></code> element, which contains
+ one <code><restriction></code> child element for every configuration
+ option the app has.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> Do not create localized versions of the restrictions
+ file. Your app is only allowed to have a single restrictions file,
+ so restrictions will be consistent for your app in all locales.
+</p>
+
+<p>
+ In an enterprise environment, an EMM will typically use the restrictions
+ schema to generate a remote console for IT administrators, so the
+ administrators can remotely configure your application.
+</p>
+
+<p>
+ For example, suppose your app can be remotely configured to allow or forbid
+ it to download data over a cellular connection. Your app could have a
+ <code><restriction></code> element like this:
+</p>
+
+<pre>
+<?xml version="1.0" encoding="utf-8"?>
+<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <restriction
+ android:key="downloadOnCellular"
+ android:title="App is allowed to download data via cellular"
+ android:restrictionType="bool"
+ android:description="If 'false', app can only download data via Wi-Fi"
+ android:defaultValue="true" />
+
+</restrictions>
+</pre>
+
+<p>
+ The supported types for the <code>android:restrictionType</code> element are
+ documented in the reference for {@link android.content.RestrictionsManager}.
+</p>
+
+<p>
+ You use each restriction's <code>android:key</code> attribute to read its
+ value from a restrictions bundle. For this reason, each restriction must have
+ a unique key string, and the string <em>cannot</em> be localized. It must be
+ specified with a string literal.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> In a production app, <code>android:title</code> and
+ <code>android:description</code> should be drawn from a localized resource
+ file, as described in <a href=
+ "{@docRoot}guide/topics/resources/localization.html">Localizing with
+ Resources</a>.
+</p>
+
+<p>
+ The restrictions provider can query the app to find details on the app's
+ available restrictions, including their description text. Restrictions
+ providers and enterprise administrators can change your app's restrictions at
+ any time, even when the app is not running.
+</p>
+
+<h2 id="check_restrictions">
+ Check App Restrictions
+</h2>
+
+<p>
+ Your app is not automatically notified when other apps change its restriction
+ settings. Instead, you need to check what the restrictions are when your app
+ starts or resumes, and listen for a system intent to find out if the
+ restrictions change while your app is running.
+</p>
+
+<p>
+ To find out the current restriction settings, your app uses a {@link
+ android.content.RestrictionsManager} object. Your app should check for the
+ current restrictions at the following times:
+</p>
+
+<ul>
+ <li>When the app starts or resumes, in its
+ {@link android.app.Activity#onResume onResume()} method
+ </li>
+
+ <li>When the app is notified of a restriction change, as described in
+ <a href="#listen">Listen for Device Configuration
+ Changes</a>
+ </li>
+</ul>
+
+<p>
+ To get a {@link android.content.RestrictionsManager} object, get the current
+ activity with {@link android.app.Fragment#getActivity getActivity()}, then
+ call that activity's {@link android.app.Activity#getSystemService
+ Activity.getSystemService()} method:
+</p>
+
+<pre>RestrictionsManager myRestrictionsMgr =
+ (RestrictionsManager) getActivity()
+ .getSystemService(Context.RESTRICTIONS_SERVICE);</pre>
+
+<p>
+ Once you have a {@link android.content.RestrictionsManager}, you can get the current restrictions
+ settings by calling its
+ {@link android.content.RestrictionsManager#getApplicationRestrictions
+ getApplicationRestrictions()} method:
+</p>
+
+<pre>Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();</pre>
+
+<p class="note">
+ <strong>Note:</strong> For convenience, you can also fetch the current
+ restrictions with a {@link android.os.UserManager}, by calling {@link
+ android.os.UserManager#getApplicationRestrictions
+ UserManager.getApplicationRestrictions()}. This method behaves exactly the
+ same as {@link android.content.RestrictionsManager#getApplicationRestrictions
+ RestrictionsManager.getApplicationRestrictions()}.
+</p>
+
+<p>
+ The {@link android.content.RestrictionsManager#getApplicationRestrictions
+ getApplicationRestrictions()} method requires reading from data storage, so
+ it should be done sparingly. Do not call this method every time you need to
+ know the current restrictions. Instead, you should call it once when your app
+ starts or resumes, and cache the fetched restrictions bundle. Then listen for
+ the {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
+ ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent to find out if restrictions
+ change while your app is active, as described in <a href="#listen">Listen for
+ Device Configuration Changes</a>.
+</p>
+
+<h3 id="read_restrictions">
+ Reading and applying restrictions
+</h3>
+
+<p>
+ The {@link android.content.RestrictionsManager#getApplicationRestrictions
+ getApplicationRestrictions()} method returns a {@link android.os.Bundle}
+ containing a key-value pair for each restriction that has been set. The
+ values are all of type <code>Boolean</code>, <code>int</code>,
+ <code>String</code>, and <code>String[]</code>. Once you have the
+ restrictions {@link android.os.Bundle}, you can check the current
+ restrictions settings with the standard {@link android.os.Bundle} methods for
+ those data types, such as {@link android.os.Bundle#getBoolean getBoolean()}
+ or
+ {@link android.os.Bundle#getString getString()}.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> The restrictions {@link android.os.Bundle} contains
+ one item for every restriction that has been explicitly set by a restrictions
+ provider. However, you <em>cannot</em> assume that a restriction will be
+ present in the bundle just because you defined a default value in the
+ restrictions XML file.
+</p>
+
+<p>
+ It is up to your app to take appropriate action based on the current
+ restrictions settings. For example, if your app has a restriction specifying
+ whether it can download data over a cellular connection, and you find that
+ the restriction is set to <code>false</code>, you would have to disable data
+ download except when the device has a Wi-Fi connection, as shown in the
+ following example code:
+</p>
+
+<pre>
+boolean appCanUseCellular;
+
+if appRestrictions.containsKey("downloadOnCellular") {
+ appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
+} else {
+ // here, cellularDefault is a boolean set with the restriction's
+ // default value
+ appCanUseCellular = cellularDefault;
+}
+
+if (!appCanUseCellular) {
+ // ...turn off app's cellular-download functionality
+ // ...show appropriate notices to user
+}</pre>
+
+<h2 id="listen">
+ Listen for App Restriction Changes
+</h2>
+
+<p>
+ Whenever an app's restrictions are changed, the system fires the
+ {@link android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED
+ ACTION_APPLICATION_RESTRICTIONS_CHANGED} intent. Your app has to listen for
+ this intent so you can change the app's behavior when the restriction settings
+ change. The following code shows how to dynamically register a broadcast
+ receiver for this intent:
+</p>
+
+<pre>IntentFilter restrictionsFilter =
+ new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
+
+BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
+ @Override public void onReceive(Context context, Intent intent) {
+
+ // Get the current restrictions bundle
+ Bundle <code>appRestrictions</code> =
+
+ myRestrictionsMgr.getApplicationRestrictions();
+
+ // Check current restrictions settings, change your app's UI and
+ // functionality as necessary.
+
+ }
+
+};
+
+registerReceiver(restrictionsReceiver, restrictionsFilter);
+</pre>
+<p class="note">
+ <strong>Note:</strong> Ordinarily, your app does not need to be notified
+ about restriction changes when it is paused. Instead, you should unregister
+ your broadcast receiver when the app is paused. When the app resumes, you
+ first check for the current restrictions (as discussed in <a href=
+ "#check_restrictions">Check Device Restrictions</a>), then register your
+ broadcast receiver to make sure you're notified about restriction changes
+ that happen while the app is active.
+</p>
diff --git a/docs/html/training/enterprise/index.jd b/docs/html/training/enterprise/index.jd
index 0ac68cc..10be14e 100644
--- a/docs/html/training/enterprise/index.jd
+++ b/docs/html/training/enterprise/index.jd
@@ -1,58 +1,67 @@
-page.title=Developing for Enterprise
-page.tags=policy,privacy
-
-trainingnavtop=true
-startpage=true
-next.title=Enhancing Security with Device Management Policies
-next.link=device-management-policy.html
+page.title=Building Apps for Work
+meta.tags="work, enterprise, corporate"
+page.tags="work", "enterprise", "corporate"
+page.metaDescription=Learn how to build Android apps for the enterprise and take advantage of Google's Android for Work program.
+page.tags="education"
+page.article=true
@jd:body
-<div id="tb-wrapper">
-<div id="tb">
+<img src="{@docRoot}images/enterprise/work-launcher.png"
+ width="300"
+ style="float:right;margin:0 0 20px 20px"
+ alt="Android for Work apps in a managed profile">
-<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
-<h2>Dependencies and prerequisites</h2>
-<ul>
- <li>Android 2.2 (API Level 8) or higher</li>
-</ul>
+<p>
+ The Android framework provides features to support the security, data separation, and
+ administration needs of a enterprise environment. As an app developer, you can make your app more
+ appealing to corporate customers by gracefully handling enterprise security and feature
+ restrictions. You can also modify your app so that technology administrators can remotely
+ configure it for use with enterprise resources.
+</p>
-<!-- related docs (NOT javadocs) -->
-<h2>You should also read</h2>
-<ul>
- <li><a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a></li>
-</ul>
+<p>
+ To help businesses incorporate Android devices and apps into the workplace, Google provides the
+ <a href="http://www.google.com/work/android">Android for Work</a> program, which offers a suite
+ of APIs and services for device distribution and administration. Through this program companies
+ can connect with Enterprise Mobility Management (EMM) providers to help integrate Android with
+ their businesses.
+</p>
-<h2>Try it out</h2>
+<p>
+ For more information, follow the links below to learn how to update your Android app to support
+ the enterprise environment or build enterprise-specific solutions.
+</p>
-<div class="download-box">
- <a href="http://developer.android.com/shareables/training/DeviceManagement.zip"
-class="button">Download the sample</a>
- <p class="filename">DeviceManagement.zip</p>
-</div>
-</div>
+<h2 id="apps">App Development for Enterprises</h2>
+
+<p>
+ Learn how to make your app function smoothly in corporate environments that restrict device
+ features and data access. Go further to support enterprise use of your app by enabling
+ restrictions that corporate technology administrators can use to remotely configure your app:
+</p>
+
+<div class="dynamic-grid">
+ <div class="resource-widget resource-flow-layout landing col-12"
+ data-query="collection:training/work/apps"
+ data-cardSizes="9x3"
+ data-maxResults="6">
+ </div>
</div>
-<p>In this class, you'll learn APIs and techniques you can use when developing applications
-for the enterprise.</p>
+<h2 id="admin">Device and App Administration</h2>
+<p>
+ Learn how to build policy controller apps that enable enterprise technology administrators
+ to manage devices, manage corporate apps, and provide access to company resources:
+</p>
-<h2>Lessons</h2>
-
-
-<dl>
- <dt><b><a href="device-management-policy.html">Enhancing Security with Device Management
-Policies</a></b></dt>
- <dd>In this lesson, you will learn how to create a security-aware application that manages
-access to its content by enforcing device management policies</dd>
-
- <dt><b><a href="app-compatibility.html">Ensuring Compatibility with Managed Profiles</a></b></dt>
-
- <dd>In this lesson, you will learn the best practices to follow to ensure
- that your app functions properly on devices that use <a
- href="{@docRoot}about/versions/android-5.0.html#Enterprise">managed
- profiles</a></dd>
-
-</dl>
+<div class="dynamic-grid">
+ <div class="resource-widget resource-flow-layout landing col-12"
+ data-query="collection:training/work/admin"
+ data-cardSizes="9x3"
+ data-maxResults="4">
+ </div>
+</div>
diff --git a/docs/html/training/enterprise/work-policy-ctrl.jd b/docs/html/training/enterprise/work-policy-ctrl.jd
new file mode 100644
index 0000000..5854e65
--- /dev/null
+++ b/docs/html/training/enterprise/work-policy-ctrl.jd
@@ -0,0 +1,339 @@
+page.title=Building a Work Policy Controller
+page.metaDescription=Learn how to develop a Work Policy Controller to create and administer a managed profile on an employee's device.
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#after_creating_profile">Create a Managed Profile</a></li>
+ <li><a href="#set_up_policies">Set Up Device Policies</a></li>
+ <li><a href="#apply_restrictions">Apply App Restrictions</a></li>
+</ol>
+
+<!-- related docs (NOT javadocs) -->
+
+<h2>
+ You should also read
+</h2>
+
+<ul>
+ <li>
+ <a href="{@docRoot}guide/topics/admin/device-admin.html">Device
+ Administration</a>
+ </li>
+</ul>
+
+<h2>Resources</h2>
+<ul>
+
+ <li>
+ <a href=
+ "{@docRoot}samples/BasicManagedProfile/index.html">BasicManagedProfile</a>
+ </li>
+
+ <li>
+ <a href=
+ "{@docRoot}samples/AppRestrictionEnforcer/index.html">AppRestrictionEnforcer</a>
+ </li>
+</ul>
+
+</div>
+</div>
+
+
+<p>
+ In an Android for Work deployment, an enterprise needs to maintain control
+ over certain aspects of the employees' devices. The enterprise needs to
+ ensure that work-related information is encrypted and is kept separate from
+ employees' personal data. The enterprise may also need to limit device
+ capabilities, such as whether the device is allowed to use its camera. And
+ the enterprise may require that approved apps provide app restrictions, so
+ the enterprise can turn app capability on or off as needed.
+</p>
+
+<p>
+ To handle these tasks, an enterprise develops and deploys a Work Policy
+ Controller app. This app is installed on each employee's device. The
+ controller app installed on each employee's device and creates a work user
+ profile, which accesses enterprise apps and data separately from the user's
+ personal account. The controller app also acts as the
+ bridge between the enterprise's management software and the device; the
+ enterprise tells the controller app when it needs to make configuration
+ changes, and the controller app makes the appropriate settings changes for the
+ device and for other apps.
+</p>
+
+<p>
+ This lesson describes how to develop a Work Policy Controller app for devices
+ in an Android for Work deployment. The lesson describes how to create a work
+ user profile, how to set device policies, and how to apply
+ restrictions to other apps running on the managed profile.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> This lesson does not cover the situation where the
+ only profile on the device is the managed profile, under the enterprise's
+ control.
+</p>
+
+<h2 id="overview">Device Administration Overview</h2>
+
+<p>
+ In an Android for Work deployment, the enterprise administrator can set
+ policies to control the behavior of employees' devices and apps. The
+ enterprise administrator sets these policies with software provided by their
+ Enterprise Mobility Management (EMM) provider. The EMM software communicates
+ with a Work Policy Controller on each device. The Work Policy Controller, in
+ turn, manages the settings and behavior of the work user profile on each
+ individual’s device.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> A Work Policy Controller is built on the existing
+ model used for device administration applications, as described in <a href=
+ "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>.
+ In particular, your app needs to create a subclass of {@link
+ android.app.admin.DeviceAdminReceiver}, as described in that document.
+</p>
+
+<h3 id="managed_profiles">Managed profiles</h3>
+
+<p>
+ Users often want to use their personal devices in an enterprise setting. This
+ situation can present enterprises with a dilemma. If the user can use their
+ own device, the enterprise has to worry that confidential information (like
+ employee emails and contacts) are on a device the enterprise does not
+ control.
+</p>
+
+<p>
+ To address this situation, Android 5.0 (API level 21) allows enterprises to
+ set up a special work user profile using the Managed Profile API. This
+ user profile is called a <em>managed profile</em>, or a <em>work profile</em>
+ in the Android for Work program. If a device has a
+ managed profile for work, the profile's settings are under the control of the
+ enterprise administrator. The administrator can choose which apps are allowed
+ for that profile, and can control just what device features are available to
+ the profile.
+</p>
+
+<h2 id="create_profile">Create a Managed Profile</h2>
+
+<p>To create a managed profile on a device that already has a personal profile,
+first check that the device can support a managed profile, by seeing if the
+device supports the {@link
+android.content.pm.PackageManager#FEATURE_MANAGED_USERS FEATURE_MANAGED_USERS}
+system feature:</p>
+
+<pre>PackageManager pm = getPackageManager();
+if (!pm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
+
+ // This device does not support native managed profiles!
+
+}</pre>
+
+<p>If the device supports managed profiles, create one by sending an intent with
+an {@link android.app.admin.DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE
+ACTION_PROVISION_MANAGED_PROFILE} action. Include the device admin package
+name as an extra.</p>
+
+<pre>Activity provisioningActivity = getActivity();
+
+// You'll need the package name for the WPC app.
+String myWPCPackageName = "com.example.myWPCApp";
+
+// Set up the provisioning intent
+Intent provisioningIntent =
+ new Intent("android.app.action.PROVISION_MANAGED_PROFILE");
+intent.putExtra(myWPCPackageName,
+ provisioningActivity.getApplicationContext().getPackageName());
+
+if (provisioningIntent.resolveActivity(provisioningActivity.getPackageManager())
+ == null) {
+
+ // No handler for intent! Can't provision this device.
+ // Show an error message and cancel.
+} else {
+
+ // REQUEST_PROVISION_MANAGED_PROFILE is defined
+ // to be a suitable request code
+ startActivityForResult(provisioningIntent,
+ REQUEST_PROVISION_MANAGED_PROFILE);
+ provisioningActivity.finish();
+}</pre>
+
+<p>The system responds to this intent by doing the following:</p>
+
+<ul>
+ <li>Verifies that the device is encrypted. If it is not, the system prompts
+ the user to encrypt the device before proceeding.
+ </li>
+
+ <li>Creates a managed profile.
+ </li>
+
+ <li>Removes non-required applications from the managed profile.
+ </li>
+
+ <li>Copies the Work Policy Controller application into the managed profile and
+ sets it as the profile owner.
+ </li>
+</ul>
+
+<p>Override {@link android.app.Activity#onActivityResult onActivityResult()} to
+see whether the provisioning was successful, as shown in the following
+example code:</p>
+
+<pre>@Override
+public void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ // Check if this is the result of the provisioning activity
+ if (requestCode == REQUEST_PROVISION_MANAGED_PROFILE) {
+
+ // If provisioning was successful, the result code is
+ // Activity.RESULT_OK
+ if (resultCode == Activity.RESULT_OK) {
+ // Hurray! Managed profile created and provisioned!
+ } else {
+ // Boo! Provisioning failed!
+ }
+ return;
+
+ } else {
+ // This is the result of some other activity, call the superclass
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+}</pre>
+
+<h3 id="after_creating_profile">After Creating the Managed Profile</h3>
+
+<p>When the profile has been provisioned, the system calls the Work Policy
+Controller app's {@link
+android.app.admin.DeviceAdminReceiver#onProfileProvisioningComplete
+DeviceAdminReceiver.onProfileProvisioningComplete()} method. Override this
+callback method to finish enabling the managed profile.</p>
+
+<p>Typically, your {@link
+android.app.admin.DeviceAdminReceiver#onProfileProvisioningComplete
+DeviceAdminReceiver.onProfileProvisioningComplete()} callback implementation
+would perform these tasks:</p>
+
+<ul>
+ <li>Verify that the device is complying with the EMM's device policies, as
+ described in <a href="#set_up_policies">Set Up Device Policies</a>
+ </li>
+
+ <li>Enable any system applications that the administrator chooses to make
+ available within the managed profile, using {@link
+ android.app.admin.DevicePolicyManager#enableSystemApp
+ DevicePolicyManager.enableSystemApp()} </li>
+
+ <li>If the device uses Google Play for Work, add the Google account
+ to the managed profile with {@link android.accounts.AccountManager#addAccount
+ AccountManager.addAccount()}, so administrators can install
+ applications to the device
+ </li>
+</ul>
+
+<p>Once you have completed these tasks, call the device policy manager's
+{@link android.app.admin.DevicePolicyManager#setProfileEnabled
+setProfileEnabled()} method to activate the managed profile:</p>
+
+
+<pre>// Get the device policy manager
+DevicePolicyManager myDevicePolicyMgr =
+ (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+ComponentName componentName = myDeviceAdminReceiver.getComponentName(this);
+
+// Set the name for the newly created managed profile.
+myDevicePolicyMgr.setProfileName(componentName, "My New Managed Profile");
+
+// ...and enable the profile
+manager.setProfileEnabled(componentName);</pre>
+
+<h2 id="set_up_policies">Set Up Device Policies</h2>
+
+<p>
+ The Work Policy Controller app is responsible for applying the enterprise's
+ device policies. For example, a particular enterprise might require that all
+ devices become locked after a certain number of failed attempts to enter the
+ device password. The controller app queries the EMM to find out what
+ the current policies are, then uses the <a href=
+ "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
+ API to apply those policies.
+</p>
+
+<p>For information on how to apply device policies, see the
+<a href="{@docRoot}guide/topics/admin/device-admin.html#policies">Device
+Administration</a> guide.</p>
+
+
+<h2 id="apply_restrictions">Apply App Restrictions</h2>
+
+<p>Enterprise environments may require that approved apps implement apps
+implement security or feature restrictions. App developers must implement these
+restrictions and declare them for use by enterprise administrators, as described
+in <a href="{@docRoot}training/enterprise/app-restrictions.html">Implementing
+App Restrictions</a>. The Work Policy Controller receives restriction changes
+from the enterprise administrator, and forwards those restriction changes to the
+apps.</p>
+
+<p>For example, a particular news app might have a restriction setting that
+controls whether the app is allowed to download videos over a cellular
+network. When the EMM wants to disable cellular downloads, it sends a
+notification to the controller app. The controller app, in turn,
+notifies the news app that the restriction setting has changed.</p>
+
+<p class="note"><strong>Note:</strong> This document covers how the Work Policy
+Controller app changes the restriction settings for the other apps on the
+managed profile. Details on how the Work Policy Controller app communicates with
+the EMM are out of scope for this document.</p>
+
+<p>To change an app's restrictions, call the {@link
+android.app.admin.DevicePolicyManager#setApplicationRestrictions
+DevicePolicyManager.setApplicationRestrictions()} method. This method is passed
+three parameters: the controller app's {@link
+android.app.admin.DeviceAdminReceiver}, the package name of the app whose
+restrictions are being changed, and a {@link android.os.Bundle Bundle} that
+contains the restrictions you want to set.</p>
+
+<p>For example, suppose there's an app on the managed profile with the package
+name <code>"com.example.newsfetcher"</code>. This app has a single boolean
+restriction that can be configured, with the key
+<code>"downloadByCellular"</code>. If this restriction is set to
+<code>false</code>, the newsfetcher app is not allowed to download data through
+a cellular network; it must use a Wi-Fi network instead.</p>
+
+<p>
+ If your Work Policy Controller app needs to turn off cellular downloads, it
+ would first fetch the device policy service object, as described above. It
+ then assembles a restrictions bundle and passes this bundle to {@link
+ android.app.admin.DevicePolicyManager#setApplicationRestrictions
+ setApplicationRestrictions()}:
+</p>
+
+<pre>// Fetch the DevicePolicyManager
+DevicePolicyManager myDevicePolicyMgr =
+ (DevicePolicyManager) thisActivity
+ .getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+// Set up the restrictions bundle
+bundle restrictionsBundle = new Bundle();
+restrictionsBundle.putBoolean("downloadByCellular", false);
+
+// Pass the restrictions to the policy manager. Assume the WPC app
+// already has a DeviceAdminReceiver defined (myDeviceAdminReceiver).
+myDevicePolicyMgr.setApplicationRestrictions(
+ myDeviceAdminReceiver, "com.example.newsfetcher", restrictionsBundle);</pre>
+
+
+<p class="note"><strong>Note:</strong> The device policy service conveys the restrictions
+change to the app you name. However, it is up to that app to actually implement
+the restriction. For example, in this case, the app would be responsible for
+disabling its ability to use cellular networks for video downloads. Setting the
+restriction does not cause the system to enforce this restriction on the app.
+For more information, see <a href="{@docRoot}training/enterprise/app-
+restrictions.html">Implementing App Restrictions</a>.</p>
diff --git a/docs/html/training/improving-layouts/optimizing-layout.jd b/docs/html/training/improving-layouts/optimizing-layout.jd
index 520ce56..003e7a2 100644
--- a/docs/html/training/improving-layouts/optimizing-layout.jd
+++ b/docs/html/training/improving-layouts/optimizing-layout.jd
@@ -126,13 +126,15 @@
<p>Most of this time difference is due to the use of {@code layout_weight} in the {@link
android.widget.LinearLayout} design, which can slow down the speed of measurement. It is just one
-example of how each layout has appropriate uses and you should carefully consider whether using
+example of how each layout has appropriate uses and you should carefully consider whether using
layout weight is necessary.</p>
<h2 id="Lint">Use Lint</h2>
-<p>It is always good practice to run the <a href="http://tools.android.com/tips/lint">Lint</a> tool on your layout files to search for possible view hierarchy optimizations. Lint has replaced the Layoutopt tool and has much greater functionality. Some examples of Lint <a
+<p>It is always good practice to run the <a href="{@docRoot}tools/help/lint.html">lint</a>
+tool on your layout files to search for possible view hierarchy optimizations. Lint has replaced
+the Layoutopt tool and has much greater functionality. Some examples of lint <a
href="http://tools.android.com/tips/lint-checks">rules</a> are:</p>
<ul>
@@ -143,11 +145,18 @@
<li>Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as {@link android.widget.RelativeLayout} or {@link android.widget.GridLayout} to improve performance. The default maximum depth is 10.</li>
</ul>
-<p>Another benefit of Lint is that it is integrated into the Android Development Tools for Eclipse (ADT 16+). Lint automatically runs whenever you export an APK, edit and save an XML file or use the Layout Editor. To manually force Lint to run press the Lint button in the Eclipse toolbar.</p>
+<p>Another benefit of Lint is that it is integrated into Android Studio. Lint automatically runs
+whenever you compile your program. With Android Studio, you can also run lint inspections for a
+specific build variant, or for all build variants. </p>
-<img src="{@docRoot}images/training/lint_icon.png" alt="" />
+<p>You can also manage inspection profiles and configure inspections within Android Studio with the
+<strong>File>Settings>Project Settings</strong> option. The Inspection Configuration page
+appears with the supported inspections.</p>
+<p><img src="{@docRoot}images/tools/studio-inspections-config.png" alt="" /> </p>
+<p class="img-caption"><strong>Figure 5.</strong> Inspection Configuration</p>
-<p>When used inside Eclipse, Lint has the ability to automatically fix some issues, provide suggestions for others and jump directly to the offending code for review. If you don’t use Eclipse for your development, Lint can also be run from the command line. More information about Lint is available at <a href="http://tools.android.com/tips/lint">tools.android.com</a>.</p>
+<p>Lint has the ability to automatically fix some issues, provide suggestions for others and jump
+directly to the offending code for review.</p>
diff --git a/docs/html/training/material/animations.jd b/docs/html/training/material/animations.jd
index efc0ee3..86e91a7 100644
--- a/docs/html/training/material/animations.jd
+++ b/docs/html/training/material/animations.jd
@@ -46,9 +46,10 @@
background as:</p>
<ul>
-<li><code>?android:attr/selectableItemBackground</code> for a bounded ripple</li>
+<li><code>?android:attr/selectableItemBackground</code> for a bounded ripple.</li>
<li><code>?android:attr/selectableItemBackgroundBorderless</code> for a ripple that extends beyond
-the view</li>
+the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null
+background.</li>
</ul>
<p class="note"><strong>Note:</strong> <code>selectableItemBackgroundBorderless</code> is a new
diff --git a/docs/html/training/multiscreen/screendensities.jd b/docs/html/training/multiscreen/screendensities.jd
index fcb65cc..64e70fd 100644
--- a/docs/html/training/multiscreen/screendensities.jd
+++ b/docs/html/training/multiscreen/screendensities.jd
@@ -28,6 +28,7 @@
<ul>
<li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+ <li><a href="{@docRoot}design/style/iconography.html">Iconography</a></li>
<li><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design
Guidelines</a></li>
</ul>
@@ -133,6 +134,28 @@
<p>Then, any time you reference <code>@drawable/awesomeimage</code>, the system selects the
appropriate bitmap based on the screen's dpi.</p>
+<p>Place your launcher icons in the <code>mipmap/</code> folders. </p>
+
+<pre>res/...
+ mipmap-ldpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-mdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-hdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxhdpi/...
+ <em>finished_launcher_asset</em>.png
+ mipmap-xxxhdpi/...
+ <em>finished_launcher_asset</em>.png
+</pre>
+
+<p class="note"><strong>Note:</strong> You should place all launcher icons in the
+<code>res/mipmap-[density]/</code> folders, rather than <code>drawable/</code> folders to ensure
+launcher apps use the best resolution icon. For more information about using the mipmap folders, see
+<a href="{@docRoot}tools/projects/index.html#mipmap">Managing Projects Overview</a>.</p>
+
<p>For more tips and guidelines for creating icon assets for your application, see the <a
href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon Design
Guidelines</a>.</p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index c59d8ff..89e72f1 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -1040,6 +1040,32 @@
<!-- End: Building for Auto -->
+ <!-- Start: Building for Work -->
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>training/enterprise/index.html">
+ <span class="small">Building Apps for</span><br/>
+ Work
+ </a>
+ </div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>training/enterprise/app-compatibility.html">
+ Ensuring Compatibility with Managed Profiles
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/enterprise/app-restrictions.html">
+ Implementing App Restrictions
+ </a>
+ </li>
+ <li><a href="<?cs var:toroot ?>training/enterprise/work-policy-ctrl.html">
+ Building a Work Policy Controller
+ </a>
+ </li>
+ </ul>
+ </li>
+ <!-- End: Building for Work -->
+
+
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/best-ux.html">
@@ -1752,10 +1778,6 @@
Enhancing Security with Device Management Policies
</a>
</li>
- <li><a href="<?cs var:toroot ?>training/enterprise/app-compatibility.html">
- Ensuring Compatibility with Managed Profiles
- </a>
- </li>
</ul>
</li>
</ul>
@@ -1887,4 +1909,4 @@
buildToggleLists();
changeNavLang(getLangPref());
//-->
-</script>
\ No newline at end of file
+</script>
diff --git a/docs/html/training/volley/request.jd b/docs/html/training/volley/request.jd
index d8ccab2..8a7dc62 100644
--- a/docs/html/training/volley/request.jd
+++ b/docs/html/training/volley/request.jd
@@ -85,7 +85,7 @@
// Retrieves an image specified by the URL, displays it in the UI.
ImageRequest request = new ImageRequest(url,
- new Response.Listener<Bitmap>() {
+ new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap bitmap) {
mImageView.setImageBitmap(bitmap);
@@ -257,7 +257,7 @@
String url = "http://my-json-feed";
JsonObjectRequest jsObjRequest = new JsonObjectRequest
- (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
+ (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
diff --git a/docs/html/training/volley/simple.jd b/docs/html/training/volley/simple.jd
index 942c57f..ecb5fde 100644
--- a/docs/html/training/volley/simple.jd
+++ b/docs/html/training/volley/simple.jd
@@ -63,7 +63,7 @@
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
- new Response.Listener<String>() {
+ new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 8fbedae..3fe5672 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -200,10 +200,11 @@
* exception. Supported formats are:
* #RRGGBB
* #AARRGGBB
+ * or one of the following names:
* 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
* 'yellow', 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey',
- * 'aqua', 'fuschia', 'lime', 'maroon', 'navy', 'olive', 'purple',
- * 'silver', 'teal'
+ * 'aqua', 'fuchsia', 'lime', 'maroon', 'navy', 'olive', 'purple',
+ * 'silver', 'teal'.
*/
public static int parseColor(String colorString) {
if (colorString.charAt(0) == '#') {
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index d2799e1..db94d89 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -20,15 +20,11 @@
import android.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff.Mode;
-import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.util.Log;
import android.os.SystemClock;
import org.xmlpull.v1.XmlPullParser;
@@ -41,35 +37,15 @@
/**
* @hide
*/
-public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
- Animatable {
- private static final String TAG = "AnimatedRotateDrawable";
-
+public class AnimatedRotateDrawable extends DrawableWrapper implements Runnable, Animatable {
private AnimatedRotateState mState;
- private boolean mMutated;
+
private float mCurrentDegrees;
private float mIncrement;
private boolean mRunning;
public AnimatedRotateDrawable() {
- this(null, null);
- }
-
- private AnimatedRotateDrawable(AnimatedRotateState rotateState, Resources res) {
- mState = new AnimatedRotateState(rotateState, this, res);
- init();
- }
-
- private void init() {
- final AnimatedRotateState state = mState;
- mIncrement = 360.0f / state.mFramesCount;
- final Drawable drawable = state.mDrawable;
- if (drawable != null) {
- drawable.setFilterBitmap(true);
- if (drawable instanceof BitmapDrawable) {
- ((BitmapDrawable) drawable).setAntiAlias(true);
- }
- }
+ this(new AnimatedRotateState(null), null);
}
@Override
@@ -131,8 +107,7 @@
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
- boolean changed = super.setVisible(visible, restart);
+ final boolean changed = super.setVisible(visible, restart);
if (visible) {
if (changed || restart) {
mCurrentDegrees = 0.0f;
@@ -144,123 +119,6 @@
return changed;
}
- /**
- * Returns the drawable rotated by this RotateDrawable.
- */
- public Drawable getDrawable() {
- return mState.mDrawable;
- }
-
- @Override
- public int getChangingConfigurations() {
- return super.getChangingConfigurations()
- | mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
- }
-
- @Override
- public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mState.mDrawable.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
- }
-
- @Override
- public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
- }
-
- @Override
- public int getOpacity() {
- return mState.mDrawable.getOpacity();
- }
-
- @Override
- public boolean canApplyTheme() {
- return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
- }
-
- @Override
- public void invalidateDrawable(Drawable who) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.invalidateDrawable(this);
- }
- }
-
- @Override
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.scheduleDrawable(this, what, when);
- }
- }
-
- @Override
- public void unscheduleDrawable(Drawable who, Runnable what) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.unscheduleDrawable(this, what);
- }
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- return mState.mDrawable.getPadding(padding);
- }
-
- @Override
- public boolean isStateful() {
- return mState.mDrawable.isStateful();
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- mState.mDrawable.setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
- }
-
- @Override
- protected boolean onLevelChange(int level) {
- return mState.mDrawable.setLevel(level);
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- return mState.mDrawable.setState(state);
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth();
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight();
- }
-
- @Override
- public ConstantState getConstantState() {
- if (mState.canConstantState()) {
- mState.mChangingConfigurations = getChangingConfigurations();
- return mState;
- }
- return null;
- }
-
@Override
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
@@ -268,50 +126,27 @@
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
a.recycle();
- inflateChildElements(r, parser, attrs, theme);
+ updateLocalState();
+ }
- init();
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (getDrawable() == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <animated-rotate> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
+ }
}
@Override
- public void applyTheme(@Nullable Theme t) {
- super.applyTheme(t);
+ void updateStateFromTypedArray(TypedArray a) {
+ super.updateStateFromTypedArray(a);
final AnimatedRotateState state = mState;
- if (state == null) {
- return;
- }
-
- if (state.mThemeAttrs != null) {
- final TypedArray a = t.resolveAttributes(
- state.mThemeAttrs, R.styleable.AnimatedRotateDrawable);
- try {
- updateStateFromTypedArray(a);
- verifyRequiredAttributes(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
- }
- }
-
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
- }
-
- init();
- }
-
- private void updateStateFromTypedArray(TypedArray a) {
- final AnimatedRotateState state = mState;
-
- // Account for any configuration changes.
- state.mChangingConfigurations |= a.getChangingConfigurations();
-
- // Extract the theme attributes, if any.
- state.mThemeAttrs = a.extractThemeAttrs();
if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) {
final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
@@ -332,43 +167,35 @@
final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable);
if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
+ setDrawable(dr);
}
}
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
+ @Override
+ public void applyTheme(@Nullable Theme t) {
final AnimatedRotateState state = mState;
+ if (state == null) {
+ return;
+ }
- Drawable dr = null;
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
- Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName());
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(
+ state.mThemeAttrs, R.styleable.AnimatedRotateDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
}
}
- if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
- }
- }
+ // The drawable may have changed as a result of applying the theme, so
+ // apply the theme to the wrapped drawable last.
+ super.applyTheme(t);
- private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
- // If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
- || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
- throw new XmlPullParserException(a.getPositionDescription()
- + ": <animated-rotate> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
- }
+ updateLocalState();
}
public void setFramesCount(int framesCount) {
@@ -380,25 +207,7 @@
mState.mFrameDuration = framesDuration;
}
- @Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
- mMutated = true;
- }
- return this;
- }
-
- /**
- * @hide
- */
- public void clearMutated() {
- super.clearMutated();
- mState.mDrawable.clearMutated();
- mMutated = false;
- }
-
- final static class AnimatedRotateState extends Drawable.ConstantState {
+ static final class AnimatedRotateState extends DrawableWrapper.DrawableWrapperState {
Drawable mDrawable;
int[] mThemeAttrs;
@@ -414,35 +223,20 @@
private boolean mCanConstantState;
private boolean mCheckedConstantState;
- public AnimatedRotateState(AnimatedRotateState orig, AnimatedRotateDrawable owner,
- Resources res) {
+ public AnimatedRotateState(AnimatedRotateState orig) {
+ super(orig);
+
if (orig != null) {
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
- mThemeAttrs = orig.mThemeAttrs;
mPivotXRel = orig.mPivotXRel;
mPivotX = orig.mPivotX;
mPivotYRel = orig.mPivotYRel;
mPivotY = orig.mPivotY;
mFramesCount = orig.mFramesCount;
mFrameDuration = orig.mFrameDuration;
- mCanConstantState = mCheckedConstantState = true;
}
}
@Override
- public Drawable newDrawable() {
- return new AnimatedRotateDrawable(this, null);
- }
-
- @Override
public Drawable newDrawable(Resources res) {
return new AnimatedRotateDrawable(this, res);
}
@@ -467,4 +261,27 @@
return mCanConstantState;
}
}
+
+ private AnimatedRotateDrawable(AnimatedRotateState state, Resources res) {
+ super(state, res);
+
+ mState = state;
+
+ updateLocalState();
+ }
+
+ private void updateLocalState() {
+ final AnimatedRotateState state = mState;
+ mIncrement = 360.0f / state.mFramesCount;
+
+ // Force the wrapped drawable to use filtering and AA, if applicable,
+ // so that it looks smooth when rotated.
+ final Drawable drawable = state.mDrawable;
+ if (drawable != null) {
+ drawable.setFilterBitmap(true);
+ if (drawable instanceof BitmapDrawable) {
+ ((BitmapDrawable) drawable).setAntiAlias(true);
+ }
+ }
+ }
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 2a17a60..17e5b0b 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -197,6 +197,11 @@
}
@Override
+ public boolean onLayoutDirectionChange(int layoutDirection) {
+ return mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
+ }
+
+ @Override
public int getAlpha() {
return mAnimatedVectorState.mVectorDrawable.getAlpha();
}
@@ -237,12 +242,6 @@
return super.setVisible(visible, restart);
}
- /** {@hide} */
- @Override
- public void setLayoutDirection(int layoutDirection) {
- mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
- }
-
@Override
public boolean isStateful() {
return mAnimatedVectorState.mVectorDrawable.isStateful();
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index e5b2b76..f3574e8 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -50,32 +50,36 @@
* @attr ref android.R.styleable#ClipDrawable_gravity
* @attr ref android.R.styleable#ClipDrawable_drawable
*/
-public class ClipDrawable extends Drawable implements Drawable.Callback {
- private ClipState mState;
- private final Rect mTmpRect = new Rect();
-
+public class ClipDrawable extends DrawableWrapper {
public static final int HORIZONTAL = 1;
public static final int VERTICAL = 2;
- private boolean mMutated;
+ private static final int MAX_LEVEL = 10000;
+
+ private final Rect mTmpRect = new Rect();
+
+ private ClipState mState;
ClipDrawable() {
- this(null, null);
+ this(new ClipState(null), null);
}
/**
- * @param orientation Bitwise-or of {@link #HORIZONTAL} and/or {@link #VERTICAL}
+ * Creates a new clip drawable with the specified gravity and orientation.
+ *
+ * @param drawable the drawable to clip
+ * @param gravity gravity constant (see {@link Gravity} used to position
+ * the clipped drawable within the parent container
+ * @param orientation bitwise-or of {@link #HORIZONTAL} and/or
+ * {@link #VERTICAL}
*/
public ClipDrawable(Drawable drawable, int gravity, int orientation) {
- this(null, null);
+ this(new ClipState(null), null);
- mState.mDrawable = drawable;
mState.mGravity = gravity;
mState.mOrientation = orientation;
- if (drawable != null) {
- drawable.setCallback(this);
- }
+ setDrawable(drawable);
}
@Override
@@ -84,39 +88,15 @@
super.inflate(r, parser, attrs, theme);
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable);
-
- // Reset mDrawable to preserve old multiple-inflate behavior. This is
- // silly, but we have CTS tests that rely on it.
- mState.mDrawable = null;
-
updateStateFromTypedArray(a);
- inflateChildElements(r, parser, attrs, theme);
+ inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
}
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- Drawable dr = null;
- int type;
- final int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- }
-
- if (dr != null) {
- mState.mDrawable = dr;
- dr.setCallback(this);
- }
- }
-
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ if (getDrawable() == null && (mState.mThemeAttrs == null
|| mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) {
throw new XmlPullParserException(a.getPositionDescription()
+ ": <clip> tag requires a 'drawable' attribute or "
@@ -124,292 +104,110 @@
}
}
- private void updateStateFromTypedArray(TypedArray a) {
+ @Override
+ void updateStateFromTypedArray(TypedArray a) {
+ super.updateStateFromTypedArray(a);
+
final ClipState state = mState;
-
- // Account for any configuration changes.
- state.mChangingConfigurations |= a.getChangingConfigurations();
-
- // Extract the theme attributes, if any.
- state.mThemeAttrs = a.extractThemeAttrs();
-
- state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
- state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity);
+ state.mOrientation = a.getInt(
+ R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
+ state.mGravity = a.getInt(
+ R.styleable.ClipDrawable_gravity, state.mGravity);
final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable);
if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
+ setDrawable(dr);
}
}
@Override
public void applyTheme(Theme t) {
- super.applyTheme(t);
-
final ClipState state = mState;
- if (state == null || state.mThemeAttrs == null) {
+ if (state == null) {
return;
}
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
- try {
- updateStateFromTypedArray(a);
- verifyRequiredAttributes(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
}
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
- }
- }
-
- @Override
- public boolean canApplyTheme() {
- return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
- }
-
- // overrides from Drawable.Callback
-
- @Override
- public void invalidateDrawable(Drawable who) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.invalidateDrawable(this);
- }
- }
-
- @Override
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.scheduleDrawable(this, what, when);
- }
- }
-
- @Override
- public void unscheduleDrawable(Drawable who, Runnable what) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.unscheduleDrawable(this, what);
- }
- }
-
- // overrides from Drawable
-
- @Override
- public int getChangingConfigurations() {
- return super.getChangingConfigurations()
- | mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- // XXX need to adjust padding!
- return mState.mDrawable.getPadding(padding);
- }
-
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
- return super.setVisible(visible, restart);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mState.mDrawable.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
- }
-
- @Override
- public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
- }
-
- @Override
- public int getOpacity() {
- return mState.mDrawable.getOpacity();
- }
-
- @Override
- public boolean isStateful() {
- return mState.mDrawable.isStateful();
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- return mState.mDrawable.setState(state);
+ // The drawable may have changed as a result of applying the theme, so
+ // apply the theme to the wrapped drawable last.
+ super.applyTheme(t);
}
@Override
protected boolean onLevelChange(int level) {
- mState.mDrawable.setLevel(level);
+ super.onLevelChange(level);
invalidateSelf();
return true;
}
@Override
- protected void onBoundsChange(Rect bounds) {
- mState.mDrawable.setBounds(bounds);
- }
-
- @Override
public void draw(Canvas canvas) {
-
- if (mState.mDrawable.getLevel() == 0) {
+ final Drawable dr = getDrawable();
+ if (dr.getLevel() == 0) {
return;
}
final Rect r = mTmpRect;
final Rect bounds = getBounds();
- int level = getLevel();
+ final int level = getLevel();
+
int w = bounds.width();
final int iw = 0; //mState.mDrawable.getIntrinsicWidth();
if ((mState.mOrientation & HORIZONTAL) != 0) {
- w -= (w - iw) * (10000 - level) / 10000;
+ w -= (w - iw) * (MAX_LEVEL - level) / MAX_LEVEL;
}
+
int h = bounds.height();
final int ih = 0; //mState.mDrawable.getIntrinsicHeight();
if ((mState.mOrientation & VERTICAL) != 0) {
- h -= (h - ih) * (10000 - level) / 10000;
+ h -= (h - ih) * (MAX_LEVEL - level) / MAX_LEVEL;
}
+
final int layoutDirection = getLayoutDirection();
Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
canvas.save();
canvas.clipRect(r);
- mState.mDrawable.draw(canvas);
+ dr.draw(canvas);
canvas.restore();
}
}
- @Override
- public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth();
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight();
- }
-
- @Override
- public ConstantState getConstantState() {
- if (mState.canConstantState()) {
- mState.mChangingConfigurations = getChangingConfigurations();
- return mState;
- }
- return null;
- }
-
- /** @hide */
- @Override
- public void setLayoutDirection(int layoutDirection) {
- mState.mDrawable.setLayoutDirection(layoutDirection);
- super.setLayoutDirection(layoutDirection);
- }
-
- @Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
- mMutated = true;
- }
- return this;
- }
-
- /**
- * @hide
- */
- public void clearMutated() {
- super.clearMutated();
- mState.mDrawable.clearMutated();
- mMutated = false;
- }
-
- final static class ClipState extends ConstantState {
- int[] mThemeAttrs;
- int mChangingConfigurations;
-
- Drawable mDrawable;
-
+ static final class ClipState extends DrawableWrapper.DrawableWrapperState {
int mOrientation = HORIZONTAL;
int mGravity = Gravity.LEFT;
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ ClipState(ClipState orig) {
+ super(orig);
- ClipState(ClipState orig, ClipDrawable owner, Resources res) {
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mChangingConfigurations = orig.mChangingConfigurations;
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
mOrientation = orig.mOrientation;
mGravity = orig.mGravity;
- mCheckedConstantState = mCanConstantState = true;
}
}
@Override
- public boolean canApplyTheme() {
- return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
- || super.canApplyTheme();
- }
-
- @Override
- public Drawable newDrawable() {
- return new ClipDrawable(this, null);
- }
-
- @Override
public Drawable newDrawable(Resources res) {
return new ClipDrawable(this, res);
}
-
- @Override
- public int getChangingConfigurations() {
- return mChangingConfigurations;
- }
-
- boolean canConstantState() {
- if (!mCheckedConstantState) {
- mCanConstantState = mDrawable.getConstantState() != null;
- mCheckedConstantState = true;
- }
-
- return mCanConstantState;
- }
}
private ClipDrawable(ClipState state, Resources res) {
- mState = new ClipState(state, this, res);
+ super(state, res);
+
+ mState = state;
}
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index fa269e0..98767a7 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -39,6 +39,7 @@
import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.IntProperty;
import android.util.StateSet;
import android.util.TypedValue;
import android.util.Xml;
@@ -422,27 +423,41 @@
* Returns the resolved layout direction for this Drawable.
*
* @return One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
- * {@link android.view.View#LAYOUT_DIRECTION_RTL}
- *
- * @hide
+ * {@link android.view.View#LAYOUT_DIRECTION_RTL}
+ * @see #setLayoutDirection(int)
*/
public int getLayoutDirection() {
return mLayoutDirection;
}
/**
- * Set the layout direction for this drawable. Should be a resolved direction as the
- * Drawable as no capacity to do the resolution on his own.
+ * Set the layout direction for this drawable. Should be a resolved
+ * layout direction, as the Drawable as no capacity to do the resolution on
+ * its own.
*
- * @param layoutDirection One of {@link android.view.View#LAYOUT_DIRECTION_LTR},
- * {@link android.view.View#LAYOUT_DIRECTION_RTL}
- *
- * @hide
+ * @param layoutDirection the resolved layout direction for the drawable,
+ * either {@link android.view.View#LAYOUT_DIRECTION_LTR}
+ * or {@link android.view.View#LAYOUT_DIRECTION_RTL}
+ * @see #getLayoutDirection()
*/
- public void setLayoutDirection(@View.ResolvedLayoutDir int layoutDirection) {
- if (getLayoutDirection() != layoutDirection) {
+ public final boolean setLayoutDirection(@View.ResolvedLayoutDir int layoutDirection) {
+ if (mLayoutDirection != layoutDirection) {
mLayoutDirection = layoutDirection;
+ return onLayoutDirectionChange(layoutDirection);
}
+ return false;
+ }
+
+ /**
+ * Called when the drawable's resolved layout direction changes.
+ *
+ * @param layoutDirection the new resolved layout direction
+ * @return true if the layout direction change has caused the appearance of
+ * the drawable to change and it needs to be re-drawn
+ * @see #setLayoutDirection(int)
+ */
+ public boolean onLayoutDirectionChange(@View.ResolvedLayoutDir int layoutDirection) {
+ return false;
}
/**
@@ -553,14 +568,20 @@
* Sets the bounds to which the hotspot is constrained, if they should be
* different from the drawable bounds.
*
- * @param left
- * @param top
- * @param right
- * @param bottom
+ * @param left position in pixels of the left bound
+ * @param top position in pixels of the top bound
+ * @param right position in pixels of the right bound
+ * @param bottom position in pixels of the bottom bound
+ * @see #getHotspotBounds(android.graphics.Rect)
*/
public void setHotspotBounds(int left, int top, int right, int bottom) {}
- /** @hide For internal use only. Individual results may vary. */
+ /**
+ * Populates {@code outRect} with the hotspot bounds.
+ *
+ * @param outRect the rect to populate with the hotspot bounds
+ * @see #setHotspotBounds(int, int, int, int)
+ */
public void getHotspotBounds(Rect outRect) {
outRect.set(getBounds());
}
@@ -1351,5 +1372,20 @@
default: return defaultMode;
}
}
+
+ /** @hide */
+ public static final IntProperty<Drawable> ALPHA = new IntProperty<Drawable>("alpha") {
+ @Override
+ public void setValue(Drawable object, int value) {
+ object.mutate();
+ object.setAlpha(value);
+ object.invalidateSelf();
+ }
+
+ @Override
+ public Integer get(Drawable object) {
+ return object.getAlpha();
+ }
+ };
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 557f563..c4794d9 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -173,7 +173,7 @@
@Override
public void setColorFilter(ColorFilter cf) {
- mDrawableContainerState.mHasColorFilter = (cf != null);
+ mDrawableContainerState.mHasColorFilter = true;
if (mDrawableContainerState.mColorFilter != cf) {
mDrawableContainerState.mColorFilter = cf;
@@ -306,7 +306,6 @@
}
}
- /** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
if (mHotspotBounds != null) {
@@ -339,6 +338,13 @@
}
@Override
+ public boolean onLayoutDirectionChange(int layoutDirection) {
+ // Let the container handle setting its own layout direction. Otherwise,
+ // we're accessing potentially unused states.
+ return mDrawableContainerState.setLayoutDirection(layoutDirection, getCurrentIndex());
+ }
+
+ @Override
public int getIntrinsicWidth() {
if (mDrawableContainerState.isConstantSize()) {
return mDrawableContainerState.getConstantWidth();
@@ -829,18 +835,25 @@
return null;
}
- final void setLayoutDirection(int layoutDirection) {
+ final boolean setLayoutDirection(int layoutDirection, int currentIndex) {
+ boolean changed = false;
+
// No need to call createAllFutures, since future drawables will
// change layout direction when they are prepared.
final int N = mNumChildren;
final Drawable[] drawables = mDrawables;
for (int i = 0; i < N; i++) {
if (drawables[i] != null) {
- drawables[i].setLayoutDirection(layoutDirection);
+ final boolean childChanged = drawables[i].setLayoutDirection(layoutDirection);
+ if (i == currentIndex) {
+ changed = childChanged;
+ }
}
}
mLayoutDirection = layoutDirection;
+
+ return changed;
}
final void applyTheme(Theme theme) {
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
new file mode 100644
index 0000000..b17bab0
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Insets;
+import android.graphics.Outline;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Drawable container with only one child element.
+ */
+public abstract class DrawableWrapper extends Drawable implements Drawable.Callback {
+ private DrawableWrapperState mState;
+ private Drawable mDrawable;
+ private boolean mMutated;
+
+ DrawableWrapper(DrawableWrapperState state, Resources res) {
+ mState = state;
+
+ updateLocalState(res);
+ }
+
+ /**
+ * Creates a new wrapper around the specified drawable.
+ *
+ * @param dr the drawable to wrap
+ */
+ public DrawableWrapper(@Nullable Drawable dr) {
+ mState = null;
+ mDrawable = dr;
+ }
+
+ /**
+ * Initializes local dynamic properties from state. This should be called
+ * after significant state changes, e.g. from the One True Constructor and
+ * after inflating or applying a theme.
+ */
+ private void updateLocalState(Resources res) {
+ if (mState != null && mState.mDrawableState != null) {
+ final Drawable dr = mState.mDrawableState.newDrawable(res);
+ setDrawable(dr);
+ }
+ }
+
+ /**
+ * Sets the wrapped drawable.
+ *
+ * @param dr the wrapped drawable
+ */
+ public void setDrawable(@Nullable Drawable dr) {
+ if (mDrawable != null) {
+ mDrawable.setCallback(null);
+ }
+
+ mDrawable = dr;
+
+ if (dr != null) {
+ dr.setCallback(this);
+
+ // Only call setters for data that's stored in the base Drawable.
+ dr.setVisible(isVisible(), true);
+ dr.setState(getState());
+ dr.setLevel(getLevel());
+ dr.setBounds(getBounds());
+ dr.setLayoutDirection(getLayoutDirection());
+
+ if (mState != null) {
+ mState.mDrawableState = dr.getConstantState();
+ }
+ }
+
+ invalidateSelf();
+ }
+
+ /**
+ * @return the wrapped drawable
+ */
+ @Nullable
+ public Drawable getDrawable() {
+ return mDrawable;
+ }
+
+ void updateStateFromTypedArray(TypedArray a) {
+ final DrawableWrapperState state = mState;
+ if (state == null) {
+ return;
+ }
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
+
+ // TODO: Consider using R.styleable.DrawableWrapper_drawable
+ }
+
+ @Override
+ public void applyTheme(Resources.Theme t) {
+ super.applyTheme(t);
+
+ final DrawableWrapperState state = mState;
+ if (state == null) {
+ return;
+ }
+
+ if (mDrawable != null && mDrawable.canApplyTheme()) {
+ mDrawable.applyTheme(t);
+ }
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
+ }
+
+ @Override
+ public void invalidateDrawable(Drawable who) {
+ final Callback callback = getCallback();
+ if (callback != null) {
+ callback.invalidateDrawable(this);
+ }
+ }
+
+ @Override
+ public void scheduleDrawable(Drawable who, Runnable what, long when) {
+ final Callback callback = getCallback();
+ if (callback != null) {
+ callback.scheduleDrawable(this, what, when);
+ }
+ }
+
+ @Override
+ public void unscheduleDrawable(Drawable who, Runnable what) {
+ final Callback callback = getCallback();
+ if (callback != null) {
+ callback.unscheduleDrawable(this, what);
+ }
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ if (mDrawable != null) {
+ mDrawable.draw(canvas);
+ }
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return super.getChangingConfigurations()
+ | (mState != null ? mState.mChangingConfigurations : 0)
+ | mDrawable.getChangingConfigurations();
+ }
+
+ @Override
+ public boolean getPadding(@NonNull Rect padding) {
+ return mDrawable != null && mDrawable.getPadding(padding);
+ }
+
+ /** @hide */
+ @Override
+ public Insets getOpticalInsets() {
+ return mDrawable != null ? mDrawable.getOpticalInsets() : Insets.NONE;
+ }
+
+ @Override
+ public void setHotspot(float x, float y) {
+ if (mDrawable != null) {
+ mDrawable.setHotspot(x, y);
+ }
+ }
+
+ @Override
+ public void setHotspotBounds(int left, int top, int right, int bottom) {
+ if (mDrawable != null) {
+ mDrawable.setHotspotBounds(left, top, right, bottom);
+ }
+ }
+
+ @Override
+ public void getHotspotBounds(@NonNull Rect outRect) {
+ if (mDrawable != null) {
+ mDrawable.getHotspotBounds(outRect);
+ } else {
+ outRect.set(getBounds());
+ }
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ final boolean superChanged = super.setVisible(visible, restart);
+ final boolean changed = mDrawable != null && mDrawable.setVisible(visible, restart);
+ return superChanged | changed;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ if (mDrawable != null) {
+ mDrawable.setAlpha(alpha);
+ }
+ }
+
+ @Override
+ public int getAlpha() {
+ return mDrawable != null ? mDrawable.getAlpha() : 255;
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter cf) {
+ if (mDrawable != null) {
+ mDrawable.setColorFilter(cf);
+ }
+ }
+
+ @Override
+ public void setTintList(@Nullable ColorStateList tint) {
+ if (mDrawable != null) {
+ mDrawable.setTintList(tint);
+ }
+ }
+
+ @Override
+ public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
+ if (mDrawable != null) {
+ mDrawable.setTintMode(tintMode);
+ }
+ }
+
+ @Override
+ public boolean onLayoutDirectionChange(@View.ResolvedLayoutDir int layoutDirection) {
+ return mDrawable != null && mDrawable.setLayoutDirection(layoutDirection);
+ }
+
+ @Override
+ public int getOpacity() {
+ return mDrawable != null ? mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mDrawable != null && mDrawable.isStateful();
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ if (mDrawable != null) {
+ final boolean changed = mDrawable.setState(state);
+ if (changed) {
+ onBoundsChange(getBounds());
+ }
+ return changed;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ return mDrawable != null && mDrawable.setLevel(level);
+ }
+
+ @Override
+ protected void onBoundsChange(@NonNull Rect bounds) {
+ if (mDrawable != null) {
+ mDrawable.setBounds(bounds);
+ }
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mDrawable != null ? mDrawable.getIntrinsicWidth() : -1;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mDrawable != null ? mDrawable.getIntrinsicHeight() : -1;
+ }
+
+ @Override
+ public void getOutline(@NonNull Outline outline) {
+ if (mDrawable != null) {
+ mDrawable.getOutline(outline);
+ } else {
+ super.getOutline(outline);
+ }
+ }
+
+ @Override
+ @Nullable
+ public ConstantState getConstantState() {
+ if (mState != null && mState.canConstantState()) {
+ mState.mChangingConfigurations = getChangingConfigurations();
+ return mState;
+ }
+ return null;
+ }
+
+ @Override
+ @NonNull
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mState = mutateConstantState();
+ if (mDrawable != null) {
+ mDrawable.mutate();
+ }
+ if (mState != null) {
+ mState.mDrawableState = mDrawable != null ? mDrawable.getConstantState() : null;
+ }
+ mMutated = true;
+ }
+ return this;
+ }
+
+ /**
+ * Mutates the constant state and returns the new state. Responsible for
+ * updating any local copy.
+ * <p>
+ * This method should never call the super implementation; it should always
+ * mutate and return its own constant state.
+ *
+ * @return the new state
+ */
+ DrawableWrapperState mutateConstantState() {
+ return mState;
+ }
+
+ /**
+ * @hide Only used by the framework for pre-loading resources.
+ */
+ public void clearMutated() {
+ super.clearMutated();
+ if (mDrawable != null) {
+ mDrawable.clearMutated();
+ }
+ mMutated = false;
+ }
+
+ /**
+ * Called during inflation to inflate the child element.
+ */
+ void inflateChildDrawable(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Resources.Theme theme) throws XmlPullParserException, IOException {
+ // Drawable specified on the root element takes precedence.
+ if (getDrawable() != null) {
+ return;
+ }
+
+ // Seek to the first child element.
+ Drawable dr = null;
+ int type;
+ final int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.START_TAG) {
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+ break;
+ }
+ }
+
+ if (dr != null) {
+ setDrawable(dr);
+ }
+ }
+
+ abstract static class DrawableWrapperState extends Drawable.ConstantState {
+ int[] mThemeAttrs;
+ int mChangingConfigurations;
+
+ Drawable.ConstantState mDrawableState;
+
+ DrawableWrapperState(DrawableWrapperState orig) {
+ if (orig != null) {
+ mThemeAttrs = orig.mThemeAttrs;
+ mChangingConfigurations = orig.mChangingConfigurations;
+ mDrawableState = orig.mDrawableState;
+ }
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null
+ || (mDrawableState != null && mDrawableState.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
+ public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
+ final Drawable.ConstantState state = mDrawableState;
+ if (state != null) {
+ return state.addAtlasableBitmaps(atlasList);
+ }
+ return 0;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return newDrawable(null);
+ }
+
+ @Override
+ public abstract Drawable newDrawable(Resources res);
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+
+ public boolean canConstantState() {
+ return mDrawableState != null;
+ }
+ }
+}
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 50a6df4..97f7105 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -18,27 +18,20 @@
import com.android.internal.R;
-import android.annotation.NonNull;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.content.res.ColorStateList;
+import android.annotation.NonNull;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
+import android.content.res.TypedArray;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.PixelFormat;
-import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.util.AttributeSet;
import java.io.IOException;
-import java.util.Collection;
/**
* A Drawable that insets another Drawable by a specified distance.
@@ -56,19 +49,16 @@
* @attr ref android.R.styleable#InsetDrawable_insetTop
* @attr ref android.R.styleable#InsetDrawable_insetBottom
*/
-public class InsetDrawable extends Drawable implements Drawable.Callback {
+public class InsetDrawable extends DrawableWrapper {
private final Rect mTmpRect = new Rect();
private InsetState mState;
- private Drawable mDrawable;
-
- private boolean mMutated;
/**
* No-arg constructor used by drawable inflation.
*/
InsetDrawable() {
- this(new InsetState(), null);
+ this(new InsetState(null), null);
}
/**
@@ -92,74 +82,31 @@
*/
public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,int insetRight,
int insetBottom) {
- this(new InsetState(), null);
+ this(new InsetState(null), null);
- mState.mDrawableState = drawable == null ? null : drawable.getConstantState();
mState.mInsetLeft = insetLeft;
mState.mInsetTop = insetTop;
mState.mInsetRight = insetRight;
mState.mInsetBottom = insetBottom;
- mDrawable = drawable;
-
- if (drawable != null) {
- drawable.setCallback(this);
- }
+ setDrawable(drawable);
}
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
- super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
+ super.inflate(r, parser, attrs, theme);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
updateStateFromTypedArray(a);
- inflateChildElements(r, parser, attrs, theme);
+ inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
}
- private void setDrawable(Drawable dr) {
- if (mDrawable != null) {
- mDrawable.setCallback(null);
- }
-
- mDrawable = dr;
-
- if (dr != null) {
- dr.setCallback(this);
- dr.setVisible(isVisible(), true);
- dr.setState(getState());
- dr.setLevel(getLevel());
- dr.setBounds(getBounds());
- dr.setLayoutDirection(getLayoutDirection());
- }
- }
-
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- // Load inner XML elements.
- if (mDrawable == null) {
- int type;
- while ((type=parser.next()) == XmlPullParser.TEXT) {
- }
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException(parser.getPositionDescription()
- + ": <inset> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
- }
-
- final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- if (dr != null) {
- mState.mDrawableState = dr.getConstantState();
- setDrawable(dr);
- }
- }
- }
-
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mDrawable == null && (mState.mThemeAttrs == null
+ if (getDrawable() == null && (mState.mThemeAttrs == null
|| mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
throw new XmlPullParserException(a.getPositionDescription()
+ ": <inset> tag requires a 'drawable' attribute or "
@@ -167,15 +114,11 @@
}
}
- private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+ @Override
+ void updateStateFromTypedArray(TypedArray a) {
+ super.updateStateFromTypedArray(a);
+
final InsetState state = mState;
-
- // Account for any configuration changes.
- state.mChangingConfigurations |= a.getChangingConfigurations();
-
- // Extract the theme attributes, if any.
- state.mThemeAttrs = a.extractThemeAttrs();
-
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
final int attr = a.getIndex(i);
@@ -183,7 +126,6 @@
case R.styleable.InsetDrawable_drawable:
final Drawable dr = a.getDrawable(attr);
if (dr != null) {
- mState.mDrawableState = dr.getConstantState();
setDrawable(dr);
}
break;
@@ -214,8 +156,6 @@
@Override
public void applyTheme(Theme t) {
- super.applyTheme(t);
-
final InsetState state = mState;
if (state == null) {
return;
@@ -233,55 +173,14 @@
}
}
- if (mDrawable != null && mDrawable.canApplyTheme()) {
- mDrawable.applyTheme(t);
- }
- }
-
- @Override
- public boolean canApplyTheme() {
- return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
- }
-
- @Override
- public void invalidateDrawable(Drawable who) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.invalidateDrawable(this);
- }
- }
-
- @Override
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.scheduleDrawable(this, what, when);
- }
- }
-
- @Override
- public void unscheduleDrawable(Drawable who, Runnable what) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.unscheduleDrawable(this, what);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- mDrawable.draw(canvas);
- }
-
- @Override
- public int getChangingConfigurations() {
- return super.getChangingConfigurations()
- | mState.mChangingConfigurations
- | mDrawable.getChangingConfigurations();
+ // The drawable may have changed as a result of applying the theme, so
+ // apply the theme to the wrapped drawable last.
+ super.applyTheme(t);
}
@Override
public boolean getPadding(Rect padding) {
- final boolean pad = mDrawable.getPadding(padding);
+ final boolean pad = super.getPadding(padding);
padding.left += mState.mInsetLeft;
padding.right += mState.mInsetRight;
@@ -303,62 +202,9 @@
}
@Override
- public void setHotspot(float x, float y) {
- mDrawable.setHotspot(x, y);
- }
-
- @Override
- public void setHotspotBounds(int left, int top, int right, int bottom) {
- mDrawable.setHotspotBounds(left, top, right, bottom);
- }
-
- /** @hide */
- @Override
- public void getHotspotBounds(Rect outRect) {
- mDrawable.getHotspotBounds(outRect);
- }
-
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- mDrawable.setVisible(visible, restart);
- return super.setVisible(visible, restart);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mDrawable.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mDrawable.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mDrawable.setColorFilter(cf);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- mDrawable.setTintList(tint);
- }
-
- @Override
- public void setTintMode(Mode tintMode) {
- mDrawable.setTintMode(tintMode);
- }
-
- /** {@hide} */
- @Override
- public void setLayoutDirection(int layoutDirection) {
- mDrawable.setLayoutDirection(layoutDirection);
- }
-
- @Override
public int getOpacity() {
final InsetState state = mState;
- final int opacity = mDrawable.getOpacity();
+ final int opacity = getDrawable().getOpacity();
if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0
|| state.mInsetRight > 0 || state.mInsetBottom > 0)) {
return PixelFormat.TRANSLUCENT;
@@ -367,23 +213,6 @@
}
@Override
- public boolean isStateful() {
- return mDrawable.isStateful();
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- final boolean changed = mDrawable.setState(state);
- onBoundsChange(getBounds());
- return changed;
- }
-
- @Override
- protected boolean onLevelChange(int level) {
- return mDrawable.setLevel(level);
- }
-
- @Override
protected void onBoundsChange(Rect bounds) {
final Rect r = mTmpRect;
r.set(bounds);
@@ -393,22 +222,23 @@
r.right -= mState.mInsetRight;
r.bottom -= mState.mInsetBottom;
- mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ // Apply inset bounds to the wrapped drawable.
+ super.onBoundsChange(r);
}
@Override
public int getIntrinsicWidth() {
- return mDrawable.getIntrinsicWidth() + mState.mInsetLeft + mState.mInsetRight;
+ return getDrawable().getIntrinsicWidth() + mState.mInsetLeft + mState.mInsetRight;
}
@Override
public int getIntrinsicHeight() {
- return mDrawable.getIntrinsicHeight() + mState.mInsetTop + mState.mInsetBottom;
+ return getDrawable().getIntrinsicHeight() + mState.mInsetTop + mState.mInsetBottom;
}
@Override
public void getOutline(@NonNull Outline outline) {
- mDrawable.getOutline(outline);
+ getDrawable().getOutline(outline);
}
@Override
@@ -421,33 +251,12 @@
}
@Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mState = new InsetState(mState);
- mDrawable.mutate();
- mState.mDrawableState = mDrawable.getConstantState();
- mMutated = true;
- }
- return this;
+ DrawableWrapperState mutateConstantState() {
+ mState = new InsetState(mState);
+ return mState;
}
- /**
- * @hide
- */
- public void clearMutated() {
- super.clearMutated();
- mDrawable.clearMutated();
- mMutated = false;
- }
-
- /**
- * Returns the drawable wrapped by this InsetDrawable. May be null.
- */
- public Drawable getDrawable() {
- return mDrawable;
- }
-
- private static final class InsetState extends ConstantState {
+ static final class InsetState extends DrawableWrapper.DrawableWrapperState {
int[] mThemeAttrs;
int mChangingConfigurations;
@@ -458,15 +267,10 @@
int mInsetRight = 0;
int mInsetBottom = 0;
- public InsetState() {
- // Empty constructor.
- }
+ InsetState(InsetState orig) {
+ super(orig);
- public InsetState(InsetState orig) {
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mChangingConfigurations = orig.mChangingConfigurations;
- mDrawableState = orig.mDrawableState;
mInsetLeft = orig.mInsetLeft;
mInsetTop = orig.mInsetTop;
mInsetRight = orig.mInsetRight;
@@ -475,39 +279,9 @@
}
@Override
- public boolean canApplyTheme() {
- return mThemeAttrs != null
- || (mDrawableState != null && mDrawableState.canApplyTheme())
- || super.canApplyTheme();
- }
-
- @Override
- public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
- final ConstantState state = mDrawableState;
- if (state != null) {
- return state.addAtlasableBitmaps(atlasList);
- }
- return 0;
- }
-
- @Override
- public Drawable newDrawable() {
- return new InsetDrawable(this, null);
- }
-
- @Override
public Drawable newDrawable(Resources res) {
return new InsetDrawable(this, res);
}
-
- @Override
- public int getChangingConfigurations() {
- return mChangingConfigurations;
- }
-
- public boolean canConstantState() {
- return mDrawableState != null;
- }
}
/**
@@ -515,21 +289,9 @@
* constructors to set the state and initialize local properties.
*/
private InsetDrawable(InsetState state, Resources res) {
+ super(state, res);
+
mState = state;
-
- updateLocalState(res);
- }
-
- /**
- * Initializes local dynamic properties from state. This should be called
- * after significant state changes, e.g. from the One True Constructor and
- * after inflating or applying a theme.
- */
- private void updateLocalState(Resources res) {
- if (mState.mDrawableState != null) {
- final Drawable dr = mState.mDrawableState.newDrawable(res);
- setDrawable(dr);
- }
}
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 9e4674b..f5353d4 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -322,7 +322,13 @@
return false;
}
- void addLayer(ChildDrawable layer) {
+ /**
+ * Adds a new layer at the end of list of layers and returns its index.
+ *
+ * @param layer The layer to add.
+ * @return The index of the layer.
+ */
+ int addLayer(ChildDrawable layer) {
final LayerState st = mLayerState;
final int N = st.mChildren != null ? st.mChildren.length : 0;
final int i = st.mNum;
@@ -338,12 +344,13 @@
st.mChildren[i] = layer;
st.mNum++;
st.invalidateCache();
+ return i;
}
/**
* Add a new layer to this drawable. The new layer is identified by an id.
*
- * @param layer The drawable to add as a layer.
+ * @param dr The drawable to add as a layer.
* @param themeAttrs Theme attributes extracted from the layer.
* @param id The id of the new layer.
* @param left The left padding of the new layer.
@@ -351,12 +358,11 @@
* @param right The right padding of the new layer.
* @param bottom The bottom padding of the new layer.
*/
- ChildDrawable addLayer(Drawable layer, int[] themeAttrs, int id, int left, int top, int right,
- int bottom) {
- final ChildDrawable childDrawable = new ChildDrawable();
+ ChildDrawable addLayer(Drawable dr, int[] themeAttrs, int id,
+ int left, int top, int right, int bottom) {
+ final ChildDrawable childDrawable = createLayer(dr);
childDrawable.mId = id;
childDrawable.mThemeAttrs = themeAttrs;
- childDrawable.mDrawable = layer;
childDrawable.mDrawable.setAutoMirrored(isAutoMirrored());
childDrawable.mInsetL = left;
childDrawable.mInsetT = top;
@@ -365,12 +371,31 @@
addLayer(childDrawable);
- mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();
- layer.setCallback(this);
+ mLayerState.mChildrenChangingConfigurations |= dr.getChangingConfigurations();
+ dr.setCallback(this);
return childDrawable;
}
+ private ChildDrawable createLayer(Drawable dr) {
+ final ChildDrawable layer = new ChildDrawable();
+ layer.mDrawable = dr;
+ return layer;
+ }
+
+ /**
+ * Adds a new layer containing the specified {@code drawable} to the end of
+ * the layer list and returns its index.
+ *
+ * @param dr The drawable to add as a new layer.
+ * @return The index of the new layer.
+ */
+ public int addLayer(Drawable dr) {
+ final ChildDrawable layer = createLayer(dr);
+ final int index = addLayer(layer);
+ return index;
+ }
+
/**
* Looks for a layer with the given ID and returns its {@link Drawable}.
* <p>
@@ -395,15 +420,38 @@
/**
* Sets the ID of a layer.
*
- * @param index The index of the layer which will received the ID.
- * @param id The ID to assign to the layer.
+ * @param index The index of the layer to modify, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @param id The id to assign to the layer.
+ *
+ * @see #getId(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_id
*/
public void setId(int index, int id) {
mLayerState.mChildren[index].mId = id;
}
/**
- * Returns the number of layers contained within this.
+ * Returns the ID of the specified layer.
+ *
+ * @param index The index of the layer, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @return The id of the layer or {@link android.view.View#NO_ID} if the
+ * layer has no id.
+ *
+ * @see #setId(int, int)
+ * @attr ref android.R.styleable#LayerDrawableItem_id
+ */
+ public int getId(int index) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mLayerState.mChildren[index].mId;
+ }
+
+ /**
+ * Returns the number of layers contained within this layer drawable.
+ *
* @return The number of layers.
*/
public int getNumberOfLayers() {
@@ -411,29 +459,7 @@
}
/**
- * Returns the drawable at the specified layer index.
- *
- * @param index The layer index of the drawable to retrieve.
- *
- * @return The {@link android.graphics.drawable.Drawable} at the specified layer index.
- */
- public Drawable getDrawable(int index) {
- return mLayerState.mChildren[index].mDrawable;
- }
-
- /**
- * Returns the id of the specified layer.
- *
- * @param index The index of the layer.
- *
- * @return The id of the layer or {@link android.view.View#NO_ID} if the layer has no id.
- */
- public int getId(int index) {
- return mLayerState.mChildren[index].mId;
- }
-
- /**
- * Sets (or replaces) the {@link Drawable} for the layer with the given id.
+ * Replaces the {@link Drawable} for the layer with the given id.
*
* @param id The layer ID to search for.
* @param drawable The replacement {@link Drawable}.
@@ -441,31 +467,88 @@
* the id was not found).
*/
public boolean setDrawableByLayerId(int id, Drawable drawable) {
+ final int index = findIndexByLayerId(id);
+ if (index < 0) {
+ return false;
+ }
+
+ setDrawable(index, drawable);
+ return true;
+ }
+
+ /**
+ * Returns the layer with the specified {@code id}.
+ * <p>
+ * If multiple layers have the same ID, returns the layer with the lowest
+ * index.
+ *
+ * @param id The ID of the layer to return.
+ * @return The index of the layer with the specified ID.
+ */
+ public int findIndexByLayerId(int id) {
final ChildDrawable[] layers = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable childDrawable = layers[i];
if (childDrawable.mId == id) {
- if (childDrawable.mDrawable != null) {
- if (drawable != null) {
- final Rect bounds = childDrawable.mDrawable.getBounds();
- drawable.setBounds(bounds);
- }
-
- childDrawable.mDrawable.setCallback(null);
- }
-
- if (drawable != null) {
- drawable.setCallback(this);
- }
-
- childDrawable.mDrawable = drawable;
- mLayerState.invalidateCache();
- return true;
+ return i;
}
}
- return false;
+ return -1;
+ }
+
+ /**
+ * Sets the drawable for the layer at the specified index.
+ *
+ * @param index The index of the layer to modify, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @param drawable The drawable to set for the layer.
+ *
+ * @see #getDrawable(int)
+ * @attr ref android.R.styleable#LayerDrawableItem_drawable
+ */
+ public void setDrawable(int index, Drawable drawable) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ final ChildDrawable[] layers = mLayerState.mChildren;
+ final ChildDrawable childDrawable = layers[index];
+ if (childDrawable.mDrawable != null) {
+ if (drawable != null) {
+ final Rect bounds = childDrawable.mDrawable.getBounds();
+ drawable.setBounds(bounds);
+ }
+
+ childDrawable.mDrawable.setCallback(null);
+ }
+
+ if (drawable != null) {
+ drawable.setCallback(this);
+ drawable.setLayoutDirection(getLayoutDirection());
+ drawable.setLevel(getLevel());
+ }
+
+ childDrawable.mDrawable = drawable;
+ mLayerState.invalidateCache();
+ }
+
+ /**
+ * Returns the drawable for the layer at the specified index.
+ *
+ * @param index The index of the layer, must be in the range
+ * {@code 0...getNumberOfLayers()-1}.
+ * @return The {@link Drawable} at the specified layer index.
+ *
+ * @see #setDrawable(int, Drawable)
+ * @attr ref android.R.styleable#LayerDrawableItem_drawable
+ */
+ public Drawable getDrawable(int index) {
+ if (index >= mLayerState.mNum) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mLayerState.mChildren[index].mDrawable;
}
/**
@@ -475,10 +558,9 @@
* default layer gravity behavior. See {@link #setLayerGravity(int, int)}
* for more information.
*
- * @param index the index of the drawable to adjust
+ * @param index the index of the layer to adjust
* @param w width in pixels, or -1 to use the intrinsic width
* @param h height in pixels, or -1 to use the intrinsic height
- *
* @see #getLayerWidth(int)
* @see #getLayerHeight(int)
* @attr ref android.R.styleable#LayerDrawableItem_width
@@ -491,9 +573,18 @@
}
/**
+ * @param index the index of the layer to adjust
+ * @param w width in pixels, or -1 to use the intrinsic width
+ * @attr ref android.R.styleable#LayerDrawableItem_width
+ */
+ public void setLayerWidth(int index, int w) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mWidth = w;
+ }
+
+ /**
* @param index the index of the drawable to adjust
* @return the explicit width of the layer, or -1 if not specified
- *
* @see #setLayerSize(int, int, int)
* @attr ref android.R.styleable#LayerDrawableItem_width
*/
@@ -503,9 +594,18 @@
}
/**
+ * @param index the index of the layer to adjust
+ * @param h height in pixels, or -1 to use the intrinsic height
+ * @attr ref android.R.styleable#LayerDrawableItem_height
+ */
+ public void setLayerHeight(int index, int h) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mHeight = h;
+ }
+
+ /**
* @param index the index of the drawable to adjust
* @return the explicit height of the layer, or -1 if not specified
- *
* @see #setLayerSize(int, int, int)
* @attr ref android.R.styleable#LayerDrawableItem_height
*/
@@ -573,7 +673,7 @@
* Specifies the relative insets in pixels for the drawable at the
* specified index.
*
- * @param index the index of the drawable to adjust
+ * @param index the index of the layer to adjust
* @param s number of pixels to inset from the start bound
* @param t number of pixels to inset from the top bound
* @param e number of pixels to inset from the end bound
@@ -588,6 +688,126 @@
setLayerInsetInternal(index, 0, t, 0, b, s, e);
}
+ /**
+ * @param index the index of the layer to adjust
+ * @param l number of pixels to inset from the left bound
+ * @attr ref android.R.styleable#LayerDrawableItem_left
+ */
+ public void setLayerInsetLeft(int index, int l) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetL = l;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the left bound
+ * @attr ref android.R.styleable#LayerDrawableItem_left
+ */
+ public int getLayerInsetLeft(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetL;
+ }
+
+ /**
+ * @param index the index of the layer to adjust
+ * @param r number of pixels to inset from the right bound
+ * @attr ref android.R.styleable#LayerDrawableItem_right
+ */
+ public void setLayerInsetRight(int index, int r) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetR = r;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the right bound
+ * @attr ref android.R.styleable#LayerDrawableItem_right
+ */
+ public int getLayerInsetRight(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetR;
+ }
+
+ /**
+ * @param index the index of the layer to adjust
+ * @param t number of pixels to inset from the top bound
+ * @attr ref android.R.styleable#LayerDrawableItem_top
+ */
+ public void setLayerInsetTop(int index, int t) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetT = t;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the top bound
+ * @attr ref android.R.styleable#LayerDrawableItem_top
+ */
+ public int getLayerInsetTop(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetT;
+ }
+
+ /**
+ * @param index the index of the layer to adjust
+ * @param b number of pixels to inset from the bottom bound
+ * @attr ref android.R.styleable#LayerDrawableItem_bottom
+ */
+ public void setLayerInsetBottom(int index, int b) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetB = b;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the bottom bound
+ * @attr ref android.R.styleable#LayerDrawableItem_bottom
+ */
+ public int getLayerInsetBottom(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetB;
+ }
+
+ /**
+ * @param index the index of the layer to adjust
+ * @param s number of pixels to inset from the start bound
+ * @attr ref android.R.styleable#LayerDrawableItem_start
+ */
+ public void setLayerInsetStart(int index, int s) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetS = s;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the start bound
+ * @attr ref android.R.styleable#LayerDrawableItem_start
+ */
+ public int getLayerInsetStart(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetS;
+ }
+
+ /**
+ * @param index the index of the layer to adjust
+ * @param e number of pixels to inset from the end bound
+ * @attr ref android.R.styleable#LayerDrawableItem_end
+ */
+ public void setLayerInsetEnd(int index, int e) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ childDrawable.mInsetE = e;
+ }
+
+ /**
+ * @param index the index of the layer
+ * @return number of pixels to inset from the end bound
+ * @attr ref android.R.styleable#LayerDrawableItem_end
+ */
+ public int getLayerInsetEnd(int index) {
+ final ChildDrawable childDrawable = mLayerState.mChildren[index];
+ return childDrawable.mInsetE;
+ }
+
private void setLayerInsetInternal(int index, int l, int t, int r, int b, int s, int e) {
final ChildDrawable childDrawable = mLayerState.mChildren[index];
childDrawable.mInsetL = l;
@@ -751,7 +971,6 @@
}
}
- /** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
if (mHotspotBounds != null) {
@@ -1147,16 +1366,16 @@
mMutated = false;
}
- /** @hide */
@Override
- public void setLayoutDirection(int layoutDirection) {
- super.setLayoutDirection(layoutDirection);
+ public boolean onLayoutDirectionChange(int layoutDirection) {
+ boolean changed = false;
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
- array[i].mDrawable.setLayoutDirection(layoutDirection);
+ changed |= array[i].mDrawable.setLayoutDirection(layoutDirection);
}
updateLayerBounds(getBounds());
+ return changed;
}
static class ChildDrawable {
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index bb1d3cb..138d73a 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -46,8 +46,7 @@
private static final long RIPPLE_ENTER_DELAY = 80;
// Hardware animators.
- private final ArrayList<RenderNodeAnimator> mRunningAnimations =
- new ArrayList<RenderNodeAnimator>();
+ private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
private final RippleDrawable mOwner;
@@ -117,8 +116,8 @@
mStartingY = startingY;
}
- public void setup(int maxRadius, float density) {
- if (maxRadius != RippleDrawable.RADIUS_AUTO) {
+ public void setup(float maxRadius, float density) {
+ if (maxRadius >= 0) {
mHasMaxRadius = true;
mOuterRadius = maxRadius;
} else {
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index fae4902..ef35289 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -49,8 +49,7 @@
private static final int ENTER_DURATION_FAST = 100;
// Hardware animators.
- private final ArrayList<RenderNodeAnimator> mRunningAnimations =
- new ArrayList<RenderNodeAnimator>();
+ private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
private final RippleDrawable mOwner;
@@ -105,8 +104,8 @@
mBounds = bounds;
}
- public void setup(int maxRadius, float density) {
- if (maxRadius != RippleDrawable.RADIUS_AUTO) {
+ public void setup(float maxRadius, float density) {
+ if (maxRadius >= 0) {
mHasMaxRadius = true;
mOuterRadius = maxRadius;
} else {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index ca9f714..c6ea91d 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -92,19 +92,17 @@
* @attr ref android.R.styleable#RippleDrawable_color
*/
public class RippleDrawable extends LayerDrawable {
+ /**
+ * Radius value that specifies the ripple radius should be computed based
+ * on the size of the ripple's container.
+ */
+ public static final int RADIUS_AUTO = -1;
+
private static final int MASK_UNKNOWN = -1;
private static final int MASK_NONE = 0;
private static final int MASK_CONTENT = 1;
private static final int MASK_EXPLICIT = 2;
- /**
- * Constant for automatically determining the maximum ripple radius.
- *
- * @see #setMaxRadius(int)
- * @hide
- */
- public static final int RADIUS_AUTO = -1;
-
/** The maximum number of ripples supported. */
private static final int MAX_RIPPLES = 10;
@@ -356,12 +354,36 @@
* Sets the ripple color.
*
* @param color Ripple color as a color state list.
+ *
+ * @attr ref android.R.styleable#RippleDrawable_color
*/
public void setColor(ColorStateList color) {
mState.mColor = color;
invalidateSelf();
}
+ /**
+ * Sets the radius in pixels of the fully expanded ripple.
+ *
+ * @param radius ripple radius in pixels, or {@link #RADIUS_AUTO} to
+ * compute the radius based on the container size
+ * @attr ref android.R.styleable#RippleDrawable_radius
+ */
+ public void setRadius(int radius) {
+ mState.mMaxRadius = radius;
+ invalidateSelf();
+ }
+
+ /**
+ * @return the radius in pixels of the fully expanded ripple if an explicit
+ * radius has been set, or {@link #RADIUS_AUTO} if the radius is
+ * computed based on the container size
+ * @attr ref android.R.styleable#RippleDrawable_radius
+ */
+ public int getRadius() {
+ return mState.mMaxRadius;
+ }
+
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
@@ -428,6 +450,9 @@
mState.mColor = color;
}
+ mState.mMaxRadius = a.getDimensionPixelSize(
+ R.styleable.RippleDrawable_radius, mState.mMaxRadius);
+
verifyRequiredAttributes(a);
}
@@ -589,7 +614,6 @@
onHotspotBoundsChanged();
}
- /** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
outRect.set(mHotspotBounds);
@@ -959,36 +983,6 @@
}
}
- /**
- * Sets the maximum ripple radius in pixels. The default value of
- * {@link #RADIUS_AUTO} defines the radius as the distance from the center
- * of the drawable bounds (or hotspot bounds, if specified) to a corner.
- *
- * @param maxRadius the maximum ripple radius in pixels or
- * {@link #RADIUS_AUTO} to automatically determine the maximum
- * radius based on the bounds
- * @see #getMaxRadius()
- * @see #setHotspotBounds(int, int, int, int)
- * @hide
- */
- public void setMaxRadius(int maxRadius) {
- if (maxRadius != RADIUS_AUTO && maxRadius < 0) {
- throw new IllegalArgumentException("maxRadius must be RADIUS_AUTO or >= 0");
- }
-
- mState.mMaxRadius = maxRadius;
- }
-
- /**
- * @return the maximum ripple radius in pixels, or {@link #RADIUS_AUTO} if
- * the radius is determined automatically
- * @see #setMaxRadius(int)
- * @hide
- */
- public int getMaxRadius() {
- return mState.mMaxRadius;
- }
-
private RippleDrawable(RippleState state, Resources res) {
mState = new RippleState(state, this, res);
mLayerState = mState;
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index e1991fe..aeef659 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -29,6 +29,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
+import android.util.MathUtils;
import android.util.TypedValue;
import android.util.AttributeSet;
@@ -51,355 +52,16 @@
* @attr ref android.R.styleable#RotateDrawable_pivotY
* @attr ref android.R.styleable#RotateDrawable_drawable
*/
-public class RotateDrawable extends Drawable implements Drawable.Callback {
- private static final float MAX_LEVEL = 10000.0f;
+public class RotateDrawable extends DrawableWrapper {
+ private static final int MAX_LEVEL = 10000;
- private final RotateState mState;
-
- private boolean mMutated;
+ private RotateState mState;
/**
* Create a new rotating drawable with an empty state.
*/
public RotateDrawable() {
- this(null, null);
- }
-
- /**
- * Create a new rotating drawable with the specified state. A copy of
- * this state is used as the internal state for the newly created
- * drawable.
- *
- * @param rotateState the state for this drawable
- */
- private RotateDrawable(RotateState rotateState, Resources res) {
- mState = new RotateState(rotateState, this, res);
- }
-
- @Override
- public void draw(Canvas canvas) {
- final RotateState st = mState;
- final Drawable d = st.mDrawable;
- final Rect bounds = d.getBounds();
- final int w = bounds.right - bounds.left;
- final int h = bounds.bottom - bounds.top;
- final float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX;
- final float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY;
-
- final int saveCount = canvas.save();
- canvas.rotate(st.mCurrentDegrees, px + bounds.left, py + bounds.top);
- d.draw(canvas);
- canvas.restoreToCount(saveCount);
- }
-
- /**
- * Sets the drawable rotated by this RotateDrawable.
- *
- * @param drawable The drawable to rotate
- */
- public void setDrawable(Drawable drawable) {
- final Drawable oldDrawable = mState.mDrawable;
- if (oldDrawable != drawable) {
- if (oldDrawable != null) {
- oldDrawable.setCallback(null);
- }
- mState.mDrawable = drawable;
- if (drawable != null) {
- drawable.setCallback(this);
- }
- }
- }
-
- /**
- * @return The drawable rotated by this RotateDrawable
- */
- public Drawable getDrawable() {
- return mState.mDrawable;
- }
-
- @Override
- public int getChangingConfigurations() {
- return super.getChangingConfigurations()
- | mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
- }
-
- @Override
- public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mState.mDrawable.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
- }
-
- @Override
- public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
- }
-
- @Override
- public int getOpacity() {
- return mState.mDrawable.getOpacity();
- }
-
- /**
- * Sets the start angle for rotation.
- *
- * @param fromDegrees Starting angle in degrees
- *
- * @see #getFromDegrees()
- * @attr ref android.R.styleable#RotateDrawable_fromDegrees
- */
- public void setFromDegrees(float fromDegrees) {
- if (mState.mFromDegrees != fromDegrees) {
- mState.mFromDegrees = fromDegrees;
- invalidateSelf();
- }
- }
-
- /**
- * @return The starting angle for rotation in degrees
- *
- * @see #setFromDegrees(float)
- * @attr ref android.R.styleable#RotateDrawable_fromDegrees
- */
- public float getFromDegrees() {
- return mState.mFromDegrees;
- }
-
- /**
- * Sets the end angle for rotation.
- *
- * @param toDegrees Ending angle in degrees
- *
- * @see #getToDegrees()
- * @attr ref android.R.styleable#RotateDrawable_toDegrees
- */
- public void setToDegrees(float toDegrees) {
- if (mState.mToDegrees != toDegrees) {
- mState.mToDegrees = toDegrees;
- invalidateSelf();
- }
- }
-
- /**
- * @return The ending angle for rotation in degrees
- *
- * @see #setToDegrees(float)
- * @attr ref android.R.styleable#RotateDrawable_toDegrees
- */
- public float getToDegrees() {
- return mState.mToDegrees;
- }
-
- /**
- * Sets the X position around which the drawable is rotated.
- *
- * @param pivotX X position around which to rotate. If the X pivot is
- * relative, the position represents a fraction of the drawable
- * width. Otherwise, the position represents an absolute value in
- * pixels.
- *
- * @see #setPivotXRelative(boolean)
- * @attr ref android.R.styleable#RotateDrawable_pivotX
- */
- public void setPivotX(float pivotX) {
- if (mState.mPivotX != pivotX) {
- mState.mPivotX = pivotX;
- invalidateSelf();
- }
- }
-
- /**
- * @return X position around which to rotate
- *
- * @see #setPivotX(float)
- * @attr ref android.R.styleable#RotateDrawable_pivotX
- */
- public float getPivotX() {
- return mState.mPivotX;
- }
-
- /**
- * Sets whether the X pivot value represents a fraction of the drawable
- * width or an absolute value in pixels.
- *
- * @param relative True if the X pivot represents a fraction of the drawable
- * width, or false if it represents an absolute value in pixels
- *
- * @see #isPivotXRelative()
- */
- public void setPivotXRelative(boolean relative) {
- if (mState.mPivotXRel != relative) {
- mState.mPivotXRel = relative;
- invalidateSelf();
- }
- }
-
- /**
- * @return True if the X pivot represents a fraction of the drawable width,
- * or false if it represents an absolute value in pixels
- *
- * @see #setPivotXRelative(boolean)
- */
- public boolean isPivotXRelative() {
- return mState.mPivotXRel;
- }
-
- /**
- * Sets the Y position around which the drawable is rotated.
- *
- * @param pivotY Y position around which to rotate. If the Y pivot is
- * relative, the position represents a fraction of the drawable
- * height. Otherwise, the position represents an absolute value
- * in pixels.
- *
- * @see #getPivotY()
- * @attr ref android.R.styleable#RotateDrawable_pivotY
- */
- public void setPivotY(float pivotY) {
- if (mState.mPivotY != pivotY) {
- mState.mPivotY = pivotY;
- invalidateSelf();
- }
- }
-
- /**
- * @return Y position around which to rotate
- *
- * @see #setPivotY(float)
- * @attr ref android.R.styleable#RotateDrawable_pivotY
- */
- public float getPivotY() {
- return mState.mPivotY;
- }
-
- /**
- * Sets whether the Y pivot value represents a fraction of the drawable
- * height or an absolute value in pixels.
- *
- * @param relative True if the Y pivot represents a fraction of the drawable
- * height, or false if it represents an absolute value in pixels
- *
- * @see #isPivotYRelative()
- */
- public void setPivotYRelative(boolean relative) {
- if (mState.mPivotYRel != relative) {
- mState.mPivotYRel = relative;
- invalidateSelf();
- }
- }
-
- /**
- * @return True if the Y pivot represents a fraction of the drawable height,
- * or false if it represents an absolute value in pixels
- *
- * @see #setPivotYRelative(boolean)
- */
- public boolean isPivotYRelative() {
- return mState.mPivotYRel;
- }
-
- @Override
- public boolean canApplyTheme() {
- return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
- }
-
- @Override
- public void invalidateDrawable(Drawable who) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.invalidateDrawable(this);
- }
- }
-
- @Override
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.scheduleDrawable(this, what, when);
- }
- }
-
- @Override
- public void unscheduleDrawable(Drawable who, Runnable what) {
- final Callback callback = getCallback();
- if (callback != null) {
- callback.unscheduleDrawable(this, what);
- }
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- return mState.mDrawable.getPadding(padding);
- }
-
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
- return super.setVisible(visible, restart);
- }
-
- @Override
- public boolean isStateful() {
- return mState.mDrawable.isStateful();
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- final boolean changed = mState.mDrawable.setState(state);
- onBoundsChange(getBounds());
- return changed;
- }
-
- @Override
- protected boolean onLevelChange(int level) {
- mState.mDrawable.setLevel(level);
- onBoundsChange(getBounds());
-
- mState.mCurrentDegrees = mState.mFromDegrees +
- (mState.mToDegrees - mState.mFromDegrees) *
- (level / MAX_LEVEL);
-
- invalidateSelf();
- return true;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- mState.mDrawable.setBounds(bounds.left, bounds.top,
- bounds.right, bounds.bottom);
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth();
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight();
- }
-
- @Override
- public ConstantState getConstantState() {
- if (mState.canConstantState()) {
- mState.mChangingConfigurations = getChangingConfigurations();
- return mState;
- }
- return null;
+ this(new RotateState(null), null);
}
@Override
@@ -408,73 +70,26 @@
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible);
- // Reset mDrawable to preserve old multiple-inflate behavior. This is
- // silly, but we have CTS tests that rely on it.
- mState.mDrawable = null;
-
updateStateFromTypedArray(a);
- inflateChildElements(r, parser, attrs, theme);
+ inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
}
- @Override
- public void applyTheme(Theme t) {
- super.applyTheme(t);
-
- final RotateState state = mState;
- if (state == null) {
- return;
- }
-
- if (state.mThemeAttrs != null) {
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable);
- try {
- updateStateFromTypedArray(a);
- verifyRequiredAttributes(a);
- } catch (XmlPullParserException e) {
- throw new RuntimeException(e);
- } finally {
- a.recycle();
- }
- }
-
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
- }
-
- }
-
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- Drawable dr = null;
- int type;
- final int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- }
-
- if (dr != null) {
- mState.mDrawable = dr;
- dr.setCallback(this);
- }
- }
-
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
- || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+ if (getDrawable() == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.RotateDrawable_drawable] == 0)) {
throw new XmlPullParserException(a.getPositionDescription()
+ ": <rotate> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
}
- private void updateStateFromTypedArray(TypedArray a) {
+ @Override
+ void updateStateFromTypedArray(TypedArray a) {
+ super.updateStateFromTypedArray(a);
+
final RotateState state = mState;
// Account for any configuration changes.
@@ -495,72 +110,235 @@
state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
}
- state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees);
- state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees);
+ state.mFromDegrees = a.getFloat(
+ R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees);
+ state.mToDegrees = a.getFloat(
+ R.styleable.RotateDrawable_toDegrees, state.mToDegrees);
state.mCurrentDegrees = state.mFromDegrees;
final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable);
if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
+ setDrawable(dr);
}
}
@Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
- mMutated = true;
+ public void applyTheme(Theme t) {
+ final RotateState state = mState;
+ if (state == null) {
+ return;
}
- return this;
+
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ // The drawable may have changed as a result of applying the theme, so
+ // apply the theme to the wrapped drawable last.
+ super.applyTheme(t);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final Drawable d = getDrawable();
+ final Rect bounds = d.getBounds();
+ final int w = bounds.right - bounds.left;
+ final int h = bounds.bottom - bounds.top;
+ final RotateState st = mState;
+ final float px = st.mPivotXRel ? (w * st.mPivotX) : st.mPivotX;
+ final float py = st.mPivotYRel ? (h * st.mPivotY) : st.mPivotY;
+
+ final int saveCount = canvas.save();
+ canvas.rotate(st.mCurrentDegrees, px + bounds.left, py + bounds.top);
+ d.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
/**
- * @hide
+ * Sets the start angle for rotation.
+ *
+ * @param fromDegrees starting angle in degrees
+ * @see #getFromDegrees()
+ * @attr ref android.R.styleable#RotateDrawable_fromDegrees
*/
- public void clearMutated() {
- super.clearMutated();
- mState.mDrawable.clearMutated();
- mMutated = false;
+ public void setFromDegrees(float fromDegrees) {
+ if (mState.mFromDegrees != fromDegrees) {
+ mState.mFromDegrees = fromDegrees;
+ invalidateSelf();
+ }
}
/**
- * Represents the state of a rotation for a given drawable. The same
- * rotate drawable can be invoked with different states to drive several
- * rotations at the same time.
+ * @return starting angle for rotation in degrees
+ * @see #setFromDegrees(float)
+ * @attr ref android.R.styleable#RotateDrawable_fromDegrees
*/
- final static class RotateState extends Drawable.ConstantState {
- int[] mThemeAttrs;
- int mChangingConfigurations;
+ public float getFromDegrees() {
+ return mState.mFromDegrees;
+ }
- Drawable mDrawable;
+ /**
+ * Sets the end angle for rotation.
+ *
+ * @param toDegrees ending angle in degrees
+ * @see #getToDegrees()
+ * @attr ref android.R.styleable#RotateDrawable_toDegrees
+ */
+ public void setToDegrees(float toDegrees) {
+ if (mState.mToDegrees != toDegrees) {
+ mState.mToDegrees = toDegrees;
+ invalidateSelf();
+ }
+ }
+ /**
+ * @return ending angle for rotation in degrees
+ * @see #setToDegrees(float)
+ * @attr ref android.R.styleable#RotateDrawable_toDegrees
+ */
+ public float getToDegrees() {
+ return mState.mToDegrees;
+ }
+
+ /**
+ * Sets the X position around which the drawable is rotated.
+ *
+ * @param pivotX X position around which to rotate. If the X pivot is
+ * relative, the position represents a fraction of the drawable
+ * width. Otherwise, the position represents an absolute value in
+ * pixels.
+ * @see #setPivotXRelative(boolean)
+ * @attr ref android.R.styleable#RotateDrawable_pivotX
+ */
+ public void setPivotX(float pivotX) {
+ if (mState.mPivotX != pivotX) {
+ mState.mPivotX = pivotX;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * @return X position around which to rotate
+ * @see #setPivotX(float)
+ * @attr ref android.R.styleable#RotateDrawable_pivotX
+ */
+ public float getPivotX() {
+ return mState.mPivotX;
+ }
+
+ /**
+ * Sets whether the X pivot value represents a fraction of the drawable
+ * width or an absolute value in pixels.
+ *
+ * @param relative true if the X pivot represents a fraction of the drawable
+ * width, or false if it represents an absolute value in pixels
+ * @see #isPivotXRelative()
+ */
+ public void setPivotXRelative(boolean relative) {
+ if (mState.mPivotXRel != relative) {
+ mState.mPivotXRel = relative;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * @return true if the X pivot represents a fraction of the drawable width,
+ * or false if it represents an absolute value in pixels
+ * @see #setPivotXRelative(boolean)
+ */
+ public boolean isPivotXRelative() {
+ return mState.mPivotXRel;
+ }
+
+ /**
+ * Sets the Y position around which the drawable is rotated.
+ *
+ * @param pivotY Y position around which to rotate. If the Y pivot is
+ * relative, the position represents a fraction of the drawable
+ * height. Otherwise, the position represents an absolute value
+ * in pixels.
+ * @see #getPivotY()
+ * @attr ref android.R.styleable#RotateDrawable_pivotY
+ */
+ public void setPivotY(float pivotY) {
+ if (mState.mPivotY != pivotY) {
+ mState.mPivotY = pivotY;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * @return Y position around which to rotate
+ * @see #setPivotY(float)
+ * @attr ref android.R.styleable#RotateDrawable_pivotY
+ */
+ public float getPivotY() {
+ return mState.mPivotY;
+ }
+
+ /**
+ * Sets whether the Y pivot value represents a fraction of the drawable
+ * height or an absolute value in pixels.
+ *
+ * @param relative True if the Y pivot represents a fraction of the drawable
+ * height, or false if it represents an absolute value in pixels
+ * @see #isPivotYRelative()
+ */
+ public void setPivotYRelative(boolean relative) {
+ if (mState.mPivotYRel != relative) {
+ mState.mPivotYRel = relative;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * @return true if the Y pivot represents a fraction of the drawable height,
+ * or false if it represents an absolute value in pixels
+ * @see #setPivotYRelative(boolean)
+ */
+ public boolean isPivotYRelative() {
+ return mState.mPivotYRel;
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ super.onLevelChange(level);
+
+ final float value = level / (float) MAX_LEVEL;
+ final float degrees = MathUtils.lerp(mState.mFromDegrees, mState.mToDegrees, value);
+ mState.mCurrentDegrees = degrees;
+
+ invalidateSelf();
+ return true;
+ }
+
+ @Override
+ DrawableWrapperState mutateConstantState() {
+ mState = new RotateState(mState);
+ return mState;
+ }
+
+ static final class RotateState extends DrawableWrapper.DrawableWrapperState {
boolean mPivotXRel = true;
float mPivotX = 0.5f;
boolean mPivotYRel = true;
float mPivotY = 0.5f;
-
float mFromDegrees = 0.0f;
float mToDegrees = 360.0f;
-
float mCurrentDegrees = 0.0f;
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ RotateState(RotateState orig) {
+ super(orig);
- RotateState(RotateState orig, RotateDrawable owner, Resources res) {
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mChangingConfigurations = orig.mChangingConfigurations;
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
mPivotXRel = orig.mPivotXRel;
mPivotX = orig.mPivotX;
mPivotYRel = orig.mPivotYRel;
@@ -568,38 +346,18 @@
mFromDegrees = orig.mFromDegrees;
mToDegrees = orig.mToDegrees;
mCurrentDegrees = orig.mCurrentDegrees;
- mCheckedConstantState = mCanConstantState = true;
}
}
@Override
- public boolean canApplyTheme() {
- return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
- || super.canApplyTheme();
- }
-
- @Override
- public Drawable newDrawable() {
- return new RotateDrawable(this, null);
- }
-
- @Override
public Drawable newDrawable(Resources res) {
return new RotateDrawable(this, res);
}
+ }
- @Override
- public int getChangingConfigurations() {
- return mChangingConfigurations;
- }
+ private RotateDrawable(RotateState state, Resources res) {
+ super(state, res);
- public boolean canConstantState() {
- if (!mCheckedConstantState) {
- mCanConstantState = mDrawable.getConstantState() != null;
- mCheckedConstantState = true;
- }
-
- return mCanConstantState;
- }
+ mState = state;
}
}
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index da722f3..0acbeda 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -21,17 +21,17 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import android.content.res.ColorStateList;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
-import android.graphics.*;
-import android.graphics.PorterDuff.Mode;
-import android.view.Gravity;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
import java.io.IOException;
-import java.util.Collection;
/**
* A Drawable that changes the size of another Drawable based on its current
@@ -49,44 +49,37 @@
* @attr ref android.R.styleable#ScaleDrawable_scaleGravity
* @attr ref android.R.styleable#ScaleDrawable_drawable
*/
-public class ScaleDrawable extends Drawable implements Drawable.Callback {
- private ScaleState mState;
- private boolean mMutated;
+public class ScaleDrawable extends DrawableWrapper {
+ private static final int MAX_LEVEL = 10000;
+
private final Rect mTmpRect = new Rect();
+ private ScaleState mState;
+
ScaleDrawable() {
- this(null, null);
+ this(new ScaleState(null), null);
}
+ /**
+ * Creates a new scale drawable with the specified gravity and scale
+ * properties.
+ *
+ * @param drawable the drawable to scale
+ * @param gravity gravity constant (see {@link Gravity} used to position
+ * the scaled drawable within the parent container
+ * @param scaleWidth width scaling factor [0...1] to use then the level is
+ * at the maximum value, or -1 to not scale width
+ * @param scaleHeight height scaling factor [0...1] to use then the level
+ * is at the maximum value, or -1 to not scale height
+ */
public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) {
- this(null, null);
+ this(new ScaleState(null), null);
- mState.mDrawable = drawable;
mState.mGravity = gravity;
mState.mScaleWidth = scaleWidth;
mState.mScaleHeight = scaleHeight;
- if (drawable != null) {
- drawable.setCallback(this);
- }
- }
-
- /**
- * Returns the drawable scaled by this ScaleDrawable.
- */
- public Drawable getDrawable() {
- return mState.mDrawable;
- }
-
- private static float getPercent(TypedArray a, int name, float defaultValue) {
- final String s = a.getString(name);
- if (s != null) {
- if (s.endsWith("%")) {
- String f = s.substring(0, s.length() - 1);
- return Float.parseFloat(f) / 100.0f;
- }
- }
- return defaultValue;
+ setDrawable(drawable);
}
@Override
@@ -95,28 +88,70 @@
super.inflate(r, parser, attrs, theme);
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable);
-
- // Reset mDrawable to preserve old multiple-inflate behavior. This is
- // silly, but we have CTS tests that rely on it.
- mState.mDrawable = null;
-
updateStateFromTypedArray(a);
- inflateChildElements(r, parser, attrs, theme);
+ inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
}
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (getDrawable() == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <scale> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
+ }
+ }
+
+ @Override
+ void updateStateFromTypedArray(TypedArray a) {
+ super.updateStateFromTypedArray(a);
+
+ final ScaleState state = mState;
+ state.mScaleWidth = getPercent(a,
+ R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth);
+ state.mScaleHeight = getPercent(a,
+ R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight);
+ state.mGravity = a.getInt(
+ R.styleable.ScaleDrawable_scaleGravity, state.mGravity);
+ state.mUseIntrinsicSizeAsMin = a.getBoolean(
+ R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, state.mUseIntrinsicSizeAsMin);
+
+ final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
+ if (dr != null) {
+ setDrawable(dr);
+ }
+ }
+
+ private static float getPercent(TypedArray a, int index, float defaultValue) {
+ final int type = a.getType(index);
+ if (type == TypedValue.TYPE_FRACTION || type == TypedValue.TYPE_NULL) {
+ return a.getFraction(index, 1, 1, defaultValue);
+ }
+
+ // Coerce to float.
+ final String s = a.getString(index);
+ if (s != null) {
+ if (s.endsWith("%")) {
+ final String f = s.substring(0, s.length() - 1);
+ return Float.parseFloat(f) / 100.0f;
+ }
+ }
+
+ return defaultValue;
+ }
+
@Override
public void applyTheme(Theme t) {
- super.applyTheme(t);
-
final ScaleState state = mState;
if (state == null) {
return;
}
if (state.mThemeAttrs != null) {
- final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable);
+ final TypedArray a = t.resolveAttributes(
+ state.mThemeAttrs, R.styleable.ScaleDrawable);
try {
updateStateFromTypedArray(a);
verifyRequiredAttributes(a);
@@ -127,161 +162,37 @@
}
}
- if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
- state.mDrawable.applyTheme(t);
- }
+ // The drawable may have changed as a result of applying the theme, so
+ // apply the theme to the wrapped drawable last.
+ super.applyTheme(t);
}
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- Drawable dr = null;
- int type;
- final int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- }
-
- if (dr != null) {
- mState.mDrawable = dr;
- dr.setCallback(this);
- }
- }
-
- private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
- // If we're not waiting on a theme, verify required attributes.
- if (mState.mDrawable == null && (mState.mThemeAttrs == null
- || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
- throw new XmlPullParserException(a.getPositionDescription()
- + ": <scale> tag requires a 'drawable' attribute or "
- + "child tag defining a drawable");
- }
- }
-
- private void updateStateFromTypedArray(TypedArray a) {
- final ScaleState state = mState;
-
- // Account for any configuration changes.
- state.mChangingConfigurations |= a.getChangingConfigurations();
-
- // Extract the theme attributes, if any.
- state.mThemeAttrs = a.extractThemeAttrs();
-
- state.mScaleWidth = getPercent(
- a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth);
- state.mScaleHeight = getPercent(
- a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight);
- state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, state.mGravity);
- state.mUseIntrinsicSizeAsMin = a.getBoolean(
- R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, state.mUseIntrinsicSizeAsMin);
-
- final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
- if (dr != null) {
- state.mDrawable = dr;
- dr.setCallback(this);
- }
- }
-
- @Override
- public boolean canApplyTheme() {
- return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
- }
-
- // overrides from Drawable.Callback
-
- public void invalidateDrawable(Drawable who) {
- if (getCallback() != null) {
- getCallback().invalidateDrawable(this);
- }
- }
-
- public void scheduleDrawable(Drawable who, Runnable what, long when) {
- if (getCallback() != null) {
- getCallback().scheduleDrawable(this, what, when);
- }
- }
-
- public void unscheduleDrawable(Drawable who, Runnable what) {
- if (getCallback() != null) {
- getCallback().unscheduleDrawable(this, what);
- }
- }
-
- // overrides from Drawable
-
@Override
public void draw(Canvas canvas) {
- if (mState.mDrawable.getLevel() != 0)
- mState.mDrawable.draw(canvas);
- }
-
- @Override
- public int getChangingConfigurations() {
- return super.getChangingConfigurations()
- | mState.mChangingConfigurations
- | mState.mDrawable.getChangingConfigurations();
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- // XXX need to adjust padding!
- return mState.mDrawable.getPadding(padding);
- }
-
- @Override
- public boolean setVisible(boolean visible, boolean restart) {
- mState.mDrawable.setVisible(visible, restart);
- return super.setVisible(visible, restart);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mState.mDrawable.setAlpha(alpha);
- }
-
- @Override
- public int getAlpha() {
- return mState.mDrawable.getAlpha();
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mState.mDrawable.setColorFilter(cf);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- mState.mDrawable.setTintList(tint);
- }
-
- @Override
- public void setTintMode(Mode tintMode) {
- mState.mDrawable.setTintMode(tintMode);
+ final Drawable d = getDrawable();
+ if (d != null && d.getLevel() != 0) {
+ d.draw(canvas);
+ }
}
@Override
public int getOpacity() {
- return mState.mDrawable.getOpacity();
- }
+ final Drawable d = getDrawable();
+ if (d.getLevel() == 0) {
+ return PixelFormat.TRANSPARENT;
+ }
- @Override
- public boolean isStateful() {
- return mState.mDrawable.isStateful();
- }
+ final int opacity = d.getOpacity();
+ if (opacity == PixelFormat.OPAQUE && d.getLevel() < MAX_LEVEL) {
+ return PixelFormat.TRANSLUCENT;
+ }
- @Override
- protected boolean onStateChange(int[] state) {
- boolean changed = mState.mDrawable.setState(state);
- onBoundsChange(getBounds());
- return changed;
+ return opacity;
}
@Override
protected boolean onLevelChange(int level) {
- mState.mDrawable.setLevel(level);
+ super.onLevelChange(level);
onBoundsChange(getBounds());
invalidateSelf();
return true;
@@ -289,144 +200,67 @@
@Override
protected void onBoundsChange(Rect bounds) {
+ final Drawable d = getDrawable();
final Rect r = mTmpRect;
final boolean min = mState.mUseIntrinsicSizeAsMin;
- int level = getLevel();
+ final int level = getLevel();
+
int w = bounds.width();
if (mState.mScaleWidth > 0) {
- final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0;
- w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000);
+ final int iw = min ? d.getIntrinsicWidth() : 0;
+ w -= (int) ((w - iw) * (MAX_LEVEL - level) * mState.mScaleWidth / MAX_LEVEL);
}
+
int h = bounds.height();
if (mState.mScaleHeight > 0) {
- final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0;
- h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000);
+ final int ih = min ? d.getIntrinsicHeight() : 0;
+ h -= (int) ((h - ih) * (MAX_LEVEL - level) * mState.mScaleHeight / MAX_LEVEL);
}
+
final int layoutDirection = getLayoutDirection();
Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
- mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ d.setBounds(r.left, r.top, r.right, r.bottom);
}
}
@Override
- public int getIntrinsicWidth() {
- return mState.mDrawable.getIntrinsicWidth();
+ DrawableWrapperState mutateConstantState() {
+ mState = new ScaleState(mState);
+ return mState;
}
- @Override
- public int getIntrinsicHeight() {
- return mState.mDrawable.getIntrinsicHeight();
- }
-
- @Override
- public ConstantState getConstantState() {
- if (mState.canConstantState()) {
- mState.mChangingConfigurations = getChangingConfigurations();
- return mState;
- }
- return null;
- }
-
- @Override
- public Drawable mutate() {
- if (!mMutated && super.mutate() == this) {
- mState.mDrawable.mutate();
- mMutated = true;
- }
- return this;
- }
-
- /**
- * @hide
- */
- public void clearMutated() {
- super.clearMutated();
- mState.mDrawable.clearMutated();
- mMutated = false;
- }
-
- final static class ScaleState extends ConstantState {
+ static final class ScaleState extends DrawableWrapper.DrawableWrapperState {
/** Constant used to disable scaling for a particular dimension. */
private static final float DO_NOT_SCALE = -1.0f;
- int[] mThemeAttrs;
- int mChangingConfigurations;
-
- Drawable mDrawable;
-
float mScaleWidth = DO_NOT_SCALE;
float mScaleHeight = DO_NOT_SCALE;
int mGravity = Gravity.LEFT;
boolean mUseIntrinsicSizeAsMin = false;
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ ScaleState(ScaleState orig) {
+ super(orig);
- ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) {
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mChangingConfigurations = orig.mChangingConfigurations;
- if (res != null) {
- mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
- } else {
- mDrawable = orig.mDrawable.getConstantState().newDrawable();
- }
- mDrawable.setCallback(owner);
- mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
- mDrawable.setBounds(orig.mDrawable.getBounds());
- mDrawable.setLevel(orig.mDrawable.getLevel());
mScaleWidth = orig.mScaleWidth;
mScaleHeight = orig.mScaleHeight;
mGravity = orig.mGravity;
mUseIntrinsicSizeAsMin = orig.mUseIntrinsicSizeAsMin;
- mCheckedConstantState = mCanConstantState = true;
}
}
@Override
- public boolean canApplyTheme() {
- return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
- || super.canApplyTheme();
- }
-
- @Override
- public Drawable newDrawable() {
- return new ScaleDrawable(this, null);
- }
-
- @Override
public Drawable newDrawable(Resources res) {
return new ScaleDrawable(this, res);
}
-
- @Override
- public int getChangingConfigurations() {
- return mChangingConfigurations;
- }
-
- boolean canConstantState() {
- if (!mCheckedConstantState) {
- mCanConstantState = mDrawable.getConstantState() != null;
- mCheckedConstantState = true;
- }
-
- return mCanConstantState;
- }
-
- @Override
- public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
- final ConstantState state = mDrawable.getConstantState();
- if (state != null) {
- return state.addAtlasableBitmaps(atlasList);
- }
- return 0;
- }
}
private ScaleDrawable(ScaleState state, Resources res) {
- mState = new ScaleState(state, this, res);
+ super(state, res);
+
+ mState = state;
}
}
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 59d0ba6..c83af11 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -309,16 +309,6 @@
mMutated = false;
}
- /** @hide */
- @Override
- public void setLayoutDirection(int layoutDirection) {
- super.setLayoutDirection(layoutDirection);
-
- // Let the container handle setting its own layout direction. Otherwise,
- // we're accessing potentially unused states.
- mStateListState.setLayoutDirection(layoutDirection);
- }
-
static class StateListState extends DrawableContainerState {
int[] mThemeAttrs;
int[][] mStateSets;
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index dfa41e8..e9c24dd 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -127,6 +127,12 @@
* Extra for use with {@link #ACTION_CHOOSER}
* @hide Also used by KeyChainActivity implementation
*/
+ public static final String EXTRA_URL = "url";
+
+ /**
+ * Extra for use with {@link #ACTION_CHOOSER}
+ * @hide Also used by KeyChainActivity implementation
+ */
public static final String EXTRA_ALIAS = "alias";
/**
@@ -224,6 +230,51 @@
* selected alias or null will be returned via the
* KeyChainAliasCallback callback.
*
+ * <p>The device or profile owner can intercept this before the activity
+ * is shown, to pick a specific private key alias.
+ *
+ * <p>{@code keyTypes} and {@code issuers} may be used to
+ * highlight suggested choices to the user, although to cope with
+ * sometimes erroneous values provided by servers, the user may be
+ * able to override these suggestions.
+ *
+ * <p>{@code host} and {@code port} may be used to give the user
+ * more context about the server requesting the credentials.
+ *
+ * <p>{@code alias} allows the chooser to preselect an existing
+ * alias which will still be subject to user confirmation.
+ *
+ * @param activity The {@link Activity} context to use for
+ * launching the new sub-Activity to prompt the user to select
+ * a private key; used only to call startActivity(); must not
+ * be null.
+ * @param response Callback to invoke when the request completes;
+ * must not be null
+ * @param keyTypes The acceptable types of asymmetric keys such as
+ * "RSA" or "DSA", or a null array.
+ * @param issuers The acceptable certificate issuers for the
+ * certificate matching the private key, or null.
+ * @param host The host name of the server requesting the
+ * certificate, or null if unavailable.
+ * @param port The port number of the server requesting the
+ * certificate, or -1 if unavailable.
+ * @param alias The alias to preselect if available, or null if
+ * unavailable.
+ */
+ public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
+ String[] keyTypes, Principal[] issuers, String host, int port, String alias) {
+ choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias);
+ }
+
+ /**
+ * Launches an {@code Activity} for the user to select the alias
+ * for a private key and certificate pair for authentication. The
+ * selected alias or null will be returned via the
+ * KeyChainAliasCallback callback.
+ *
+ * <p>The device or profile owner can intercept this before the activity
+ * is shown, to pick a specific private key alias.</p>
+ *
* <p>{@code keyTypes} and {@code issuers} may be used to
* highlight suggested choices to the user, although to cope with
* sometimes erroneous values provided by servers, the user may be
@@ -249,12 +300,14 @@
* certificate, or null if unavailable.
* @param port The port number of the server requesting the
* certificate, or -1 if unavailable.
+ * @param url The full url the server is requesting the certificate
+ * for, or null if unavailable.
* @param alias The alias to preselect if available, or null if
* unavailable.
*/
public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
String[] keyTypes, Principal[] issuers,
- String host, int port,
+ String host, int port, String url,
String alias) {
/*
* TODO currently keyTypes, issuers are unused. They are meant
@@ -283,6 +336,7 @@
intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
intent.putExtra(EXTRA_HOST, host);
intent.putExtra(EXTRA_PORT, port);
+ intent.putExtra(EXTRA_URL, url);
intent.putExtra(EXTRA_ALIAS, alias);
// the PendingIntent is used to get calling package name
intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index e753a7c..bfbf028 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -18,8 +18,14 @@
import com.android.org.conscrypt.NativeCrypto;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.security.keymaster.ExportResult;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.OperationResult;
import android.util.Log;
import java.util.Locale;
@@ -58,6 +64,8 @@
private final IKeystoreService mBinder;
+ private IBinder mToken;
+
private KeyStore(IKeystoreService binder) {
mBinder = binder;
}
@@ -68,6 +76,13 @@
return new KeyStore(keystore);
}
+ private synchronized IBinder getToken() {
+ if (mToken == null) {
+ mToken = new Binder();
+ }
+ return mToken;
+ }
+
static int getKeyTypeForAlgorithm(String keyType) {
if ("RSA".equalsIgnoreCase(keyType)) {
return NativeCrypto.EVP_PKEY_RSA;
@@ -363,4 +378,100 @@
public int getLastError() {
return mError;
}
+
+ public boolean addRngEntropy(byte[] data) {
+ try {
+ return mBinder.addRngEntropy(data) == NO_ERROR;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return false;
+ }
+ }
+
+ public int generateKey(String alias, KeymasterArguments args, int uid, int flags,
+ KeyCharacteristics outCharacteristics) {
+ try {
+ return mBinder.generateKey(alias, args, uid, flags, outCharacteristics);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
+
+ public int generateKey(String alias, KeymasterArguments args, int flags,
+ KeyCharacteristics outCharacteristics) {
+ return generateKey(alias, args, UID_SELF, flags, outCharacteristics);
+ }
+
+ public int getKeyCharacteristics(String alias, byte[] clientId, byte[] appId,
+ KeyCharacteristics outCharacteristics) {
+ try {
+ return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
+
+ public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
+ int uid, int flags, KeyCharacteristics outCharacteristics) {
+ try {
+ return mBinder.importKey(alias, args, format, keyData, uid, flags,
+ outCharacteristics);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
+
+ public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
+ int flags, KeyCharacteristics outCharacteristics) {
+ return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
+ }
+
+ public ExportResult exportKey(String alias, int format, byte[] clientId, byte[] appId) {
+ try {
+ return mBinder.exportKey(alias, format, clientId, appId);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ }
+ }
+
+ public OperationResult begin(String alias, int purpose, boolean pruneable,
+ KeymasterArguments args, KeymasterArguments outArgs) {
+ try {
+ return mBinder.begin(getToken(), alias, purpose, pruneable, args, outArgs);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ }
+ }
+
+ public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
+ try {
+ return mBinder.update(token, arguments, input);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ }
+ }
+
+ public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
+ try {
+ return mBinder.finish(token, arguments, signature);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ }
+ }
+
+ public int abort(IBinder token) {
+ try {
+ return mBinder.abort(token);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
}
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 4b3382e..782806e 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -532,7 +532,7 @@
void _FileAsset::close(void)
{
if (mMap != NULL) {
- mMap->release();
+ delete mMap;
mMap = NULL;
}
if (mBuf != NULL) {
@@ -612,7 +612,7 @@
map = new FileMap;
if (!map->create(NULL, fileno(mFp), mStart, mLength, true)) {
- map->release();
+ delete map;
return NULL;
}
@@ -827,7 +827,7 @@
void _CompressedAsset::close(void)
{
if (mMap != NULL) {
- mMap->release();
+ delete mMap;
mMap = NULL;
}
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index ef0d072..af3d9b3 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -200,7 +200,7 @@
FileMap* newMap = new FileMap();
if (!newMap->create(mFileName, fd, ze.offset, actualLen, true)) {
- newMap->release();
+ delete newMap;
return NULL;
}
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index e05dd55..5dacbb5 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -43,11 +43,13 @@
Extensions.cpp \
FboCache.cpp \
FontRenderer.cpp \
+ FrameInfo.cpp \
GammaFontRenderer.cpp \
GlopBuilder.cpp \
GradientCache.cpp \
Image.cpp \
Interpolator.cpp \
+ JankTracker.cpp \
Layer.cpp \
LayerCache.cpp \
LayerRenderer.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f4fc068..bd933b8 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -263,7 +263,7 @@
const Layer* layer = *it;
log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
layer->getWidth(), layer->getHeight(),
- layer->isTextureLayer(), layer->getTexture(),
+ layer->isTextureLayer(), layer->getTextureId(),
layer->getFbo(), layer->getStrongCount());
memused += layer->getWidth() * layer->getHeight() * 4;
}
@@ -405,7 +405,7 @@
///////////////////////////////////////////////////////////////////////////////
void Caches::initTempProperties() {
- propertyLightDiameter = -1.0f;
+ propertyLightRadius = -1.0f;
propertyLightPosY = -1.0f;
propertyLightPosZ = -1.0f;
propertyAmbientRatio = -1.0f;
@@ -419,9 +419,9 @@
propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
return;
- } else if (!strcmp(name, "lightDiameter")) {
- propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
- ALOGD("lightDiameter = %.2f", propertyLightDiameter);
+ } else if (!strcmp(name, "lightRadius")) {
+ propertyLightRadius = fmin(fmax(atof(value), 0.0), 3000.0);
+ ALOGD("lightRadius = %.2f", propertyLightRadius);
return;
} else if (!strcmp(name, "lightPosY")) {
propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 18bb5e6..92a87e2 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -214,7 +214,7 @@
void initTempProperties();
void setTempProperty(const char* name, const char* value);
- float propertyLightDiameter;
+ float propertyLightRadius;
float propertyLightPosY;
float propertyLightPosZ;
float propertyAmbientRatio;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 0792120..6a59a13 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -62,7 +62,7 @@
if (mSurfaceTexture.get()) {
if (mNeedsGLContextAttach) {
mNeedsGLContextAttach = false;
- mSurfaceTexture->attachToContext(mLayer->getTexture());
+ mSurfaceTexture->attachToContext(mLayer->getTextureId());
}
if (mUpdateTexImage) {
mUpdateTexImage = false;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index d128ffe..cca8a06 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -668,7 +668,8 @@
}
virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top,
+ OP_LOG("Draw bitmap %p of size %dx%d%s",
+ mBitmap, mBitmap->width(), mBitmap->height(),
mEntry ? " using AssetAtlas" : "");
}
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
new file mode 100644
index 0000000..97dec88
--- /dev/null
+++ b/libs/hwui/FloatColor.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef FLOATCOLOR_H
+#define FLOATCOLOR_H
+
+#include "utils/Macros.h"
+
+#include <stdint.h>
+
+namespace android {
+namespace uirenderer {
+
+struct FloatColor {
+ void set(uint32_t color) {
+ a = ((color >> 24) & 0xff) / 255.0f;
+ r = a * ((color >> 16) & 0xff) / 255.0f;
+ g = a * ((color >> 8) & 0xff) / 255.0f;
+ b = a * ((color ) & 0xff) / 255.0f;
+ }
+
+ bool isNotBlack() {
+ return a < 1.0f
+ || r > 0.0f
+ || g > 0.0f
+ || b > 0.0f;
+ }
+
+ float r;
+ float g;
+ float b;
+ float a;
+};
+
+REQUIRE_COMPATIBLE_LAYOUT(FloatColor);
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* FLOATCOLOR_H */
diff --git a/core/java/android/midi/IMidiDeviceServer.aidl b/libs/hwui/FrameInfo.cpp
similarity index 63%
copy from core/java/android/midi/IMidiDeviceServer.aidl
copy to libs/hwui/FrameInfo.cpp
index 31fdbbb..6da1fa8 100644
--- a/core/java/android/midi/IMidiDeviceServer.aidl
+++ b/libs/hwui/FrameInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "FrameInfo.h"
-package android.midi;
+#include <cstring>
-import android.os.ParcelFileDescriptor;
+namespace android {
+namespace uirenderer {
-/** @hide */
-interface IMidiDeviceServer
-{
- ParcelFileDescriptor openInputPort(int portNumber);
- ParcelFileDescriptor openOutputPort(int portNumber);
+void FrameInfo::importUiThreadInfo(int64_t* info) {
+ memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
new file mode 100644
index 0000000..65daf03
--- /dev/null
+++ b/libs/hwui/FrameInfo.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef FRAMEINFO_H_
+#define FRAMEINFO_H_
+
+#include "utils/Macros.h"
+
+#include <cutils/compiler.h>
+#include <utils/Timers.h>
+
+#include <memory.h>
+
+namespace android {
+namespace uirenderer {
+
+#define UI_THREAD_FRAME_INFO_SIZE 9
+
+enum class FrameInfoIndex {
+ kFlags = 0,
+ kIntendedVsync,
+ kVsync,
+ kOldestInputEvent,
+ kNewestInputEvent,
+ kHandleInputStart,
+ kAnimationStart,
+ kPerformTraversalsStart,
+ kDrawStart,
+ // End of UI frame info
+
+ kSyncStart,
+ kIssueDrawCommandsStart,
+ kSwapBuffers,
+ kFrameCompleted,
+
+ // Must be the last value!
+ kNumIndexes
+};
+
+enum class FrameInfoFlags {
+ kWindowLayoutChanged = 1 << 0,
+ kRTAnimation = 1 << 1,
+ kSurfaceCanvas = 1 << 2,
+};
+MAKE_FLAGS_ENUM(FrameInfoFlags)
+
+class ANDROID_API UiFrameInfoBuilder {
+public:
+ UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
+ memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+ }
+
+ UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
+ set(FrameInfoIndex::kVsync) = vsyncTime;
+ set(FrameInfoIndex::kIntendedVsync) = intendedVsync;
+ return *this;
+ }
+
+ UiFrameInfoBuilder& addFlag(FrameInfoFlags flag) {
+ set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag);
+ return *this;
+ }
+
+private:
+ inline int64_t& set(FrameInfoIndex index) {
+ return mBuffer[static_cast<int>(index)];
+ }
+
+ int64_t* mBuffer;
+};
+
+class FrameInfo {
+public:
+ void importUiThreadInfo(int64_t* info);
+
+ void markSyncStart() {
+ set(FrameInfoIndex::kSyncStart) = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markIssueDrawCommandsStart() {
+ set(FrameInfoIndex::kIssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markSwapBuffers() {
+ set(FrameInfoIndex::kSwapBuffers) = systemTime(CLOCK_MONOTONIC);
+ }
+
+ void markFrameCompleted() {
+ set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC);
+ }
+
+ int64_t operator[](FrameInfoIndex index) const {
+ if (index == FrameInfoIndex::kNumIndexes) return 0;
+ return mFrameInfo[static_cast<int>(index)];
+ }
+
+ int64_t operator[](int index) const {
+ if (index < 0 || index >= static_cast<int>(FrameInfoIndex::kNumIndexes)) return 0;
+ return mFrameInfo[index];
+ }
+
+private:
+ inline int64_t& set(FrameInfoIndex index) {
+ return mFrameInfo[static_cast<int>(index)];
+ }
+
+ int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::kNumIndexes)];
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* FRAMEINFO_H_ */
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index e2adff8..e500546 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -17,8 +17,11 @@
#ifndef ANDROID_HWUI_GLOP_H
#define ANDROID_HWUI_GLOP_H
+#include "FloatColor.h"
#include "Matrix.h"
+#include "Program.h"
#include "Rect.h"
+#include "SkiaShader.h"
#include "utils/Macros.h"
#include <GLES2/gl2.h>
@@ -29,6 +32,8 @@
namespace uirenderer {
class Program;
+class RoundRectClipState;
+class Texture;
/*
* Enumerates optional vertex attributes
@@ -37,30 +42,27 @@
* are enabled/disabled dynamically based on mesh content.
*/
enum VertexAttribFlags {
- // NOTE: position attribute always enabled
kNone_Attrib = 0,
kTextureCoord_Attrib = 1 << 0,
kColor_Attrib = 1 << 1,
kAlpha_Attrib = 1 << 2,
};
-
/**
- * Structure containing all data required to issue a single OpenGL draw
+ * Structure containing all data required to issue an OpenGL draw
*
* Includes all of the mesh, fill, and GL state required to perform
* the operation. Pieces of data are either directly copied into the
* structure, or stored as a pointer or GL object reference to data
- * managed
+ * managed.
+ *
+ * Eventually, a Glop should be able to be drawn multiple times from
+ * a single construction, up until GL context destruction. Currently,
+ * vertex/index/Texture/RoundRectClipState pointers prevent this from
+ * being safe.
*/
// TODO: PREVENT_COPY_AND_ASSIGN(...) or similar
struct Glop {
- struct FloatColor {
- float a, r, g, b;
- };
-
- Rect bounds;
-
/*
* Stores mesh - vertex and index data.
*
@@ -74,19 +76,24 @@
GLuint indexBufferObject;
const void* vertices;
const void* indices;
- int vertexCount;
+ GLvoid* texCoordOffset;
+ int elementCount;
GLsizei stride;
+ TextureVertex mappedVertices[4];
} mesh;
struct Fill {
Program* program;
+
+ struct TextureData {
+ Texture* texture;
+ GLenum filter;
+ GLenum clamp;
+ } texture;
+
+ bool colorEnabled;
FloatColor color;
- /* TODO
- union shader {
- //...
- }; TODO
- */
ProgramDescription::ColorFilterMode filterMode;
union Filter {
struct Matrix {
@@ -95,6 +102,8 @@
} matrix;
FloatColor color;
} filter;
+
+ SkiaShaderData skiaShaderData;
} fill;
struct Transform {
@@ -104,12 +113,25 @@
bool fudgingOffset;
} transform;
+ const RoundRectClipState* roundRectClipState;
+
+ /**
+ * Blending to be used by this draw - both GL_NONE if blending is disabled.
+ *
+ * Defined by fill step, but can be force-enabled by presence of kAlpha_Attrib
+ */
struct Blend {
GLenum src;
GLenum dst;
} blend;
/**
+ * Bounds of the drawing command in layer space. Only mapped into layer
+ * space once GlopBuilder::build() is called.
+ */
+ Rect bounds;
+
+ /**
* Additional render state to enumerate:
* - scissor + (bits for whether each of LTRB needed?)
* - stencil mode (draw into, mask, count, etc)
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 5373275..4617588 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -33,19 +33,106 @@
#define TRIGGER_STAGE(stageFlag) \
LOG_ALWAYS_FATAL_IF(stageFlag & mStageFlags, "Stage %d cannot be run twice"); \
- mStageFlags = static_cast<StageFlags>(mStageFlags | stageFlag)
+ mStageFlags = static_cast<StageFlags>(mStageFlags | (stageFlag))
#define REQUIRE_STAGES(requiredFlags) \
- LOG_ALWAYS_FATAL_IF((mStageFlags & requiredFlags) != requiredFlags, \
+ LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \
"not prepared for current stage")
+static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
+ TextureVertex::setUV(quadVertex++, uvs.left, uvs.top);
+ TextureVertex::setUV(quadVertex++, uvs.right, uvs.top);
+ TextureVertex::setUV(quadVertex++, uvs.left, uvs.bottom);
+ TextureVertex::setUV(quadVertex++, uvs.right, uvs.bottom);
+}
+
GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop)
: mRenderState(renderState)
, mCaches(caches)
- , mOutGlop(outGlop){
+ , mShader(nullptr)
+ , mOutGlop(outGlop) {
mStageFlags = kInitialStage;
}
+////////////////////////////////////////////////////////////////////////////////
+// Mesh
+////////////////////////////////////////////////////////////////////////////////
+
+GlopBuilder& GlopBuilder::setMeshUnitQuad() {
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.vertexFlags = kNone_Attrib;
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
+ mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
+ mOutGlop->mesh.vertices = nullptr;
+ mOutGlop->mesh.indexBufferObject = 0;
+ mOutGlop->mesh.indices = nullptr;
+ mOutGlop->mesh.elementCount = 4;
+ mOutGlop->mesh.stride = kTextureVertexStride;
+ mOutGlop->mesh.texCoordOffset = nullptr;
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib;
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
+
+ if (CC_UNLIKELY(uvMapper)) {
+ Rect uvs(0, 0, 1, 1);
+ uvMapper->map(uvs);
+ setUnitQuadTextureCoords(uvs, &mOutGlop->mesh.mappedVertices[0]);
+
+ mOutGlop->mesh.vertexBufferObject = 0;
+ mOutGlop->mesh.vertices = &mOutGlop->mesh.mappedVertices[0];
+ mOutGlop->mesh.texCoordOffset = &mOutGlop->mesh.mappedVertices[0].u;
+ } else {
+ // standard UV coordinates, use regular unit quad VBO
+ mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
+ mOutGlop->mesh.vertices = nullptr;
+ mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset;
+ }
+ mOutGlop->mesh.indexBufferObject = 0;
+ mOutGlop->mesh.indices = nullptr;
+ mOutGlop->mesh.elementCount = 4;
+ mOutGlop->mesh.stride = kTextureVertexStride;
+ mDescription.hasTexture = true;
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) {
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.vertexFlags = kNone_Attrib;
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
+ mOutGlop->mesh.vertexBufferObject = 0;
+ mOutGlop->mesh.vertices = vertexData;
+ mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO();
+ mOutGlop->mesh.indices = nullptr;
+ mOutGlop->mesh.texCoordOffset = nullptr;
+ mOutGlop->mesh.elementCount = 6 * quadCount;
+ mOutGlop->mesh.stride = kVertexStride;
+
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount) {
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib;
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
+ mOutGlop->mesh.vertexBufferObject = 0;
+ mOutGlop->mesh.vertices = &vertexData[0].x;
+ mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO();
+ mOutGlop->mesh.indices = nullptr;
+ mOutGlop->mesh.texCoordOffset = &vertexData[0].u;
+ mOutGlop->mesh.elementCount = elementCount;
+ mOutGlop->mesh.stride = kTextureVertexStride;
+ mDescription.hasTexture = true;
+ return *this;
+}
+
GlopBuilder& GlopBuilder::setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp) {
TRIGGER_STAGE(kMeshStage);
@@ -59,7 +146,8 @@
mOutGlop->mesh.vertices = vertexBuffer.getBuffer();
mOutGlop->mesh.indexBufferObject = 0;
mOutGlop->mesh.indices = vertexBuffer.getIndices();
- mOutGlop->mesh.vertexCount = indices
+ mOutGlop->mesh.texCoordOffset = nullptr;
+ mOutGlop->mesh.elementCount = indices
? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride;
@@ -68,115 +156,35 @@
return *this;
}
-GlopBuilder& GlopBuilder::setMeshUnitQuad() {
- TRIGGER_STAGE(kMeshStage);
+////////////////////////////////////////////////////////////////////////////////
+// Fill
+////////////////////////////////////////////////////////////////////////////////
- mOutGlop->mesh.vertexFlags = kNone_Attrib;
- mOutGlop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
- mOutGlop->mesh.vertexBufferObject = mRenderState.meshState().getUnitQuadVBO();
- mOutGlop->mesh.vertices = nullptr;
- mOutGlop->mesh.indexBufferObject = 0;
- mOutGlop->mesh.indices = nullptr;
- mOutGlop->mesh.vertexCount = 4;
- mOutGlop->mesh.stride = kTextureVertexStride;
- return *this;
-}
-
-GlopBuilder& GlopBuilder::setMeshIndexedQuads(void* vertexData, int quadCount) {
- TRIGGER_STAGE(kMeshStage);
-
- mOutGlop->mesh.vertexFlags = kNone_Attrib;
- mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
- mOutGlop->mesh.vertexBufferObject = 0;
- mOutGlop->mesh.vertices = vertexData;
- mOutGlop->mesh.indexBufferObject = mRenderState.meshState().getQuadListIBO();
- mOutGlop->mesh.indices = nullptr;
- mOutGlop->mesh.vertexCount = 6 * quadCount;
- mOutGlop->mesh.stride = kVertexStride;
-
- return *this;
-}
-
-GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho,
- const Matrix4& transform, bool fudgingOffset) {
- TRIGGER_STAGE(kTransformStage);
-
- mOutGlop->transform.ortho.load(ortho);
- mOutGlop->transform.canvas.load(transform);
- mOutGlop->transform.fudgingOffset = fudgingOffset;
- return *this;
-}
-
-GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
- TRIGGER_STAGE(kModelViewStage);
-
- mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
- mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
- mOutGlop->bounds = destination;
- return *this;
-}
-
-GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) {
- TRIGGER_STAGE(kModelViewStage);
-
- mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
- mOutGlop->bounds = source;
- mOutGlop->bounds.translate(offsetX, offsetY);
- return *this;
-}
-
-GlopBuilder& GlopBuilder::setOptionalPaint(const SkPaint* paint, float alphaScale) {
- if (paint) {
- return setPaint(*paint, alphaScale);
- }
-
- TRIGGER_STAGE(kFillStage);
- REQUIRE_STAGES(kMeshStage);
-
- mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
-
- const bool SWAP_SRC_DST = false;
- // TODO: account for texture blend
- if (alphaScale < 1.0f
- || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)) {
- Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST,
- &mOutGlop->blend.src, &mOutGlop->blend.dst);
- } else {
- mOutGlop->blend = { GL_ZERO, GL_ZERO };
- }
-
- return *this;
-}
-GlopBuilder& GlopBuilder::setPaint(const SkPaint& paint, float alphaScale) {
- TRIGGER_STAGE(kFillStage);
- REQUIRE_STAGES(kMeshStage);
-
- const SkShader* shader = paint.getShader();
- const SkColorFilter* colorFilter = paint.getColorFilter();
-
- SkXfermode::Mode mode = PaintUtils::getXfermode(paint.getXfermode());
+void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode,
+ const SkShader* shader, const SkColorFilter* colorFilter) {
if (mode != SkXfermode::kClear_Mode) {
- int color = paint.getColor();
float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
if (!shader) {
float colorScale = alpha / 255.0f;
mOutGlop->fill.color = {
- alpha,
colorScale * SkColorGetR(color),
colorScale * SkColorGetG(color),
- colorScale * SkColorGetB(color)
+ colorScale * SkColorGetB(color),
+ alpha
};
} else {
- mOutGlop->fill.color = { alpha, 1, 1, 1 };
+ mOutGlop->fill.color = { 1, 1, 1, alpha };
}
} else {
- mOutGlop->fill.color = { 1, 0, 0, 0 };
+ mOutGlop->fill.color = { 0, 0, 0, 1 };
}
const bool SWAP_SRC_DST = false;
mOutGlop->blend = { GL_ZERO, GL_ZERO };
if (mOutGlop->fill.color.a < 1.0f
|| (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)
+ || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
+ || mOutGlop->roundRectClipState
|| PaintUtils::isBlendedShader(shader)
|| PaintUtils::isBlendedColorFilter(colorFilter)
|| mode != SkXfermode::kSrcOver_Mode) {
@@ -200,12 +208,7 @@
}
}
}
-
- if (shader) {
- SkiaShader::describe(&mCaches, mDescription, mCaches.extensions(), *shader);
- // TODO: store shader data
- LOG_ALWAYS_FATAL("shaders not yet supported");
- }
+ mShader = shader; // shader resolved in ::build()
if (colorFilter) {
SkColor color;
@@ -218,10 +221,10 @@
const float alpha = SkColorGetA(color) / 255.0f;
float colorScale = alpha / 255.0f;
mOutGlop->fill.filter.color = {
- alpha,
colorScale * SkColorGetR(color),
colorScale * SkColorGetG(color),
colorScale * SkColorGetB(color),
+ alpha,
};
} else if (colorFilter->asColorMatrix(srcColorMatrix)) {
mOutGlop->fill.filterMode = mDescription.colorOp = ProgramDescription::kColorMatrix;
@@ -245,18 +248,255 @@
} else {
mOutGlop->fill.filterMode = ProgramDescription::kColorNone;
}
+}
+GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture,
+ const SkPaint* paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = { &texture, PaintUtils::getFilter(paint), GL_CLAMP_TO_EDGE };
+
+ if (paint) {
+ int color = paint->getColor();
+ SkShader* shader = paint->getShader();
+
+ if (!isAlphaMaskTexture) {
+ // Texture defines color, so disable shaders, and reset all non-alpha color channels
+ color |= 0x00FFFFFF;
+ shader = nullptr;
+ }
+ setFill(color, alphaScale, PaintUtils::getXfermode(paint->getXfermode()),
+ shader, paint->getColorFilter());
+ } else {
+ mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
+
+ const bool SWAP_SRC_DST = false;
+ if (alphaScale < 1.0f
+ || (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)
+ || texture.blend
+ || mOutGlop->roundRectClipState) {
+ Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST,
+ &mOutGlop->blend.src, &mOutGlop->blend.dst);
+ } else {
+ mOutGlop->blend = { GL_ZERO, GL_ZERO };
+ }
+ }
+
+ mDescription.hasAlpha8Texture = isAlphaMaskTexture;
+ if (isAlphaMaskTexture) {
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
+ } else {
+ mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+ }
return *this;
}
+GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM };
+
+ setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
+ paint.getShader(), paint.getColorFilter());
+ mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
+ const SkPaint& paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ //specify invalid filter/clamp, since these are always static for PathTextures
+ mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM };
+
+ setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
+ paint.getShader(), paint.getColorFilter());
+
+ mDescription.hasAlpha8Texture = true;
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
+ const SkPaint& paint, float alphaScale) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ //specify invalid filter/clamp, since these are always static for ShadowTextures
+ mOutGlop->fill.texture = { &texture, GL_INVALID_ENUM, GL_INVALID_ENUM };
+
+ const int ALPHA_BITMASK = SK_ColorBLACK;
+ const int COLOR_BITMASK = ~ALPHA_BITMASK;
+ if ((shadowColor & ALPHA_BITMASK) == ALPHA_BITMASK) {
+ // shadow color is fully opaque: override its alpha with that of paint
+ shadowColor &= paint.getColor() | COLOR_BITMASK;
+ }
+
+ setFill(shadowColor, alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
+ paint.getShader(), paint.getColorFilter());
+
+ mDescription.hasAlpha8Texture = true;
+ mDescription.modulate = mOutGlop->fill.color.isNotBlack();
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillBlack() {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM };
+ setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, nullptr, nullptr);
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillClear() {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM };
+ setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, nullptr, nullptr);
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
+ float alpha, SkXfermode::Mode mode) {
+ TRIGGER_STAGE(kFillStage);
+ REQUIRE_STAGES(kMeshStage);
+
+ mOutGlop->fill.texture = { &texture, GL_LINEAR, GL_CLAMP_TO_EDGE };
+ mOutGlop->fill.color = { alpha, alpha, alpha, alpha };
+
+ setFill(SK_ColorWHITE, alpha, mode, nullptr, colorFilter);
+
+ mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Transform
+////////////////////////////////////////////////////////////////////////////////
+
+GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho,
+ const Matrix4& transform, bool fudgingOffset) {
+ TRIGGER_STAGE(kTransformStage);
+
+ mOutGlop->transform.ortho.load(ortho);
+ mOutGlop->transform.canvas.load(transform);
+ mOutGlop->transform.fudgingOffset = fudgingOffset;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ModelView
+////////////////////////////////////////////////////////////////////////////////
+
+GlopBuilder& GlopBuilder::setModelViewMapUnitToRect(const Rect destination) {
+ TRIGGER_STAGE(kModelViewStage);
+
+ mOutGlop->transform.modelView.loadTranslate(destination.left, destination.top, 0.0f);
+ mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
+ mOutGlop->bounds = destination;
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setModelViewMapUnitToRectSnap(const Rect destination) {
+ TRIGGER_STAGE(kModelViewStage);
+ REQUIRE_STAGES(kTransformStage | kFillStage);
+
+ float left = destination.left;
+ float top = destination.top;
+
+ const Matrix4& canvasTransform = mOutGlop->transform.canvas;
+ if (CC_LIKELY(canvasTransform.isPureTranslate())) {
+ // snap by adjusting the model view matrix
+ const float translateX = canvasTransform.getTranslateX();
+ const float translateY = canvasTransform.getTranslateY();
+
+ left = (int) floorf(left + translateX + 0.5f) - translateX;
+ top = (int) floorf(top + translateY + 0.5f) - translateY;
+ mOutGlop->fill.texture.filter = GL_NEAREST;
+ }
+
+ mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
+ mOutGlop->transform.modelView.scale(destination.getWidth(), destination.getHeight(), 1.0f);
+ mOutGlop->bounds = destination;
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setModelViewOffsetRect(float offsetX, float offsetY, const Rect source) {
+ TRIGGER_STAGE(kModelViewStage);
+
+ mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
+ mOutGlop->bounds = source;
+ mOutGlop->bounds.translate(offsetX, offsetY);
+ return *this;
+}
+
+GlopBuilder& GlopBuilder::setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source) {
+ TRIGGER_STAGE(kModelViewStage);
+ REQUIRE_STAGES(kTransformStage | kFillStage);
+
+ const Matrix4& canvasTransform = mOutGlop->transform.canvas;
+ if (CC_LIKELY(canvasTransform.isPureTranslate())) {
+ // snap by adjusting the model view matrix
+ const float translateX = canvasTransform.getTranslateX();
+ const float translateY = canvasTransform.getTranslateY();
+
+ offsetX = (int) floorf(offsetX + translateX + source.left + 0.5f) - translateX - source.left;
+ offsetY = (int) floorf(offsetY + translateY + source.top + 0.5f) - translateY - source.top;
+ mOutGlop->fill.texture.filter = GL_NEAREST;
+ }
+
+ mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
+ mOutGlop->bounds.translate(offsetX, offsetY);
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// RoundRectClip
+////////////////////////////////////////////////////////////////////////////////
+
+GlopBuilder& GlopBuilder::setRoundRectClipState(const RoundRectClipState* roundRectClipState) {
+ TRIGGER_STAGE(kRoundRectClipStage);
+
+ mOutGlop->roundRectClipState = roundRectClipState;
+ mDescription.hasRoundRectClip = roundRectClipState != nullptr;
+ return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Build
+////////////////////////////////////////////////////////////////////////////////
+
+void verify(const ProgramDescription& description, const Glop& glop) {
+ bool hasTexture = glop.fill.texture.texture != nullptr;
+ LOG_ALWAYS_FATAL_IF(description.hasTexture != hasTexture);
+ LOG_ALWAYS_FATAL_IF((glop.mesh.vertexFlags & kTextureCoord_Attrib) != hasTexture);
+}
+
void GlopBuilder::build() {
REQUIRE_STAGES(kAllStages);
- mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+ // serialize shader info into ShaderData
+ GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
+ SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView,
+ &textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
+
mOutGlop->fill.program = mCaches.programCache.get(mDescription);
mOutGlop->transform.canvas.mapRect(mOutGlop->bounds);
+
+ // duplicates ProgramCache's definition of color uniform presence
+ const bool singleColor = !mDescription.hasTexture
+ && !mDescription.hasExternalTexture
+ && !mDescription.hasGradient
+ && !mDescription.hasBitmap;
+ mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;
+
+ verify(mDescription, *mOutGlop);
}
} /* namespace uirenderer */
} /* namespace android */
-
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 48ce81a..cbdd0cd 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -21,16 +21,17 @@
#include "utils/Macros.h"
class SkPaint;
+class SkShader;
namespace android {
namespace uirenderer {
class Caches;
-struct Glop;
class Matrix4;
class RenderState;
class Texture;
class VertexBuffer;
+struct Glop;
class GlopBuilder {
PREVENT_COPY_AND_ASSIGN(GlopBuilder);
@@ -38,30 +39,51 @@
GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop);
GlopBuilder& setMeshUnitQuad();
+ GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper);
GlopBuilder& setMeshVertexBuffer(const VertexBuffer& vertexBuffer, bool shadowInterp);
GlopBuilder& setMeshIndexedQuads(void* vertexData, int quadCount);
+ GlopBuilder& setMeshTexturedIndexedQuads(TextureVertex* vertexData, int elementCount); // TODO: take quadCount
+
+ GlopBuilder& setFillPaint(const SkPaint& paint, float alphaScale);
+ GlopBuilder& setFillTexturePaint(Texture& texture, bool isAlphaMaskTexture,
+ const SkPaint* paint, float alphaScale);
+ GlopBuilder& setFillPathTexturePaint(PathTexture& texture,
+ const SkPaint& paint, float alphaScale);
+ GlopBuilder& setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
+ const SkPaint& paint, float alphaScale);
+ GlopBuilder& setFillBlack();
+ GlopBuilder& setFillClear();
+ GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
+ float alpha, SkXfermode::Mode mode);
GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
+ GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination);
GlopBuilder& setModelViewOffsetRect(float offsetX, float offsetY, const Rect source);
+ GlopBuilder& setModelViewOffsetRectSnap(float offsetX, float offsetY, const Rect source);
- GlopBuilder& setOptionalPaint(const SkPaint* paint, float alphaScale);
- GlopBuilder& setPaint(const SkPaint& paint, float alphaScale);
+ GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState);
+
void build();
private:
+ void setFill(int color, float alphaScale, SkXfermode::Mode mode,
+ const SkShader* shader, const SkColorFilter* colorFilter);
+
enum StageFlags {
kInitialStage = 0,
kMeshStage = 1 << 0,
kTransformStage = 1 << 1,
kModelViewStage = 1 << 2,
kFillStage = 1 << 3,
- kAllStages = kMeshStage | kTransformStage | kModelViewStage | kFillStage,
+ kRoundRectClipStage = 1 << 4,
+ kAllStages = kMeshStage | kFillStage | kTransformStage | kModelViewStage | kRoundRectClipStage,
} mStageFlags;
ProgramDescription mDescription;
RenderState& mRenderState;
Caches& mCaches;
+ const SkShader* mShader;
Glop* mOutGlop;
};
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index fb4c785..ea93e7f 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -166,7 +166,7 @@
GradientInfo info;
getGradientInfo(colors, count, info);
- Texture* texture = new Texture();
+ Texture* texture = new Texture(Caches::getInstance());
texture->width = info.width;
texture->height = 2;
texture->blend = info.hasAlpha;
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
new file mode 100644
index 0000000..d0ea3a6
--- /dev/null
+++ b/libs/hwui/JankTracker.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "JankTracker.h"
+
+#include <cstdio>
+#include <inttypes.h>
+
+namespace android {
+namespace uirenderer {
+
+static const char* JANK_TYPE_NAMES[] = {
+ "Missed Vsync",
+ "High input latency",
+ "Slow UI thread",
+ "Slow bitmap uploads",
+ "Slow draw",
+};
+
+struct Comparison {
+ FrameInfoIndex start;
+ FrameInfoIndex end;
+};
+
+static const Comparison COMPARISONS[] = {
+ {FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync},
+ {FrameInfoIndex::kOldestInputEvent, FrameInfoIndex::kVsync},
+ {FrameInfoIndex::kVsync, FrameInfoIndex::kSyncStart},
+ {FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart},
+ {FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kFrameCompleted},
+};
+
+// If the event exceeds 10 seconds throw it away, this isn't a jank event
+// it's an ANR and will be handled as such
+static const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10);
+
+/*
+ * Frames that are exempt from jank metrics.
+ * First-draw frames, for example, are expected to
+ * be slow, this is hidden from the user with window animations and
+ * other tricks
+ *
+ * Similarly, we don't track direct-drawing via Surface:lockHardwareCanvas()
+ * for now
+ *
+ * TODO: kSurfaceCanvas can negatively impact other drawing by using up
+ * time on the RenderThread, figure out how to attribute that as a jank-causer
+ */
+static const int64_t EXEMPT_FRAMES_FLAGS
+ = FrameInfoFlags::kWindowLayoutChanged
+ | FrameInfoFlags::kSurfaceCanvas;
+
+JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
+ reset();
+ setFrameInterval(frameIntervalNanos);
+}
+
+void JankTracker::setFrameInterval(nsecs_t frameInterval) {
+ mFrameInterval = frameInterval;
+ mThresholds[kMissedVsync] = 1;
+ /*
+ * Due to interpolation and sample rate differences between the touch
+ * panel and the display (example, 85hz touch panel driving a 60hz display)
+ * we call high latency 1.5 * frameinterval
+ *
+ * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
+ * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
+ * Thus this must always be larger than frameInterval, or it will fail
+ */
+ mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
+
+ // Note that these do not add up to 1. This is intentional. It's to deal
+ // with variance in values, and should be sort of an upper-bound on what
+ // is reasonable to expect.
+ mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
+ mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
+ mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
+
+}
+
+void JankTracker::addFrame(const FrameInfo& frame) {
+ mTotalFrameCount++;
+ // Fast-path for jank-free frames
+ int64_t totalDuration =
+ frame[FrameInfoIndex::kFrameCompleted] - frame[FrameInfoIndex::kIntendedVsync];
+ if (CC_LIKELY(totalDuration < mFrameInterval)) {
+ return;
+ }
+
+ if (frame[FrameInfoIndex::kFlags] & EXEMPT_FRAMES_FLAGS) {
+ return;
+ }
+
+ mJankFrameCount++;
+
+ for (int i = 0; i < NUM_BUCKETS; i++) {
+ int64_t delta = frame[COMPARISONS[i].end] - frame[COMPARISONS[i].start];
+ if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
+ mBuckets[i].count++;
+ }
+ }
+}
+
+void JankTracker::dump(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\nFrame stats:");
+ fprintf(file, "\n Total frames rendered: %u", mTotalFrameCount);
+ fprintf(file, "\n Janky frames: %u (%.2f%%)", mJankFrameCount,
+ (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
+ for (int i = 0; i < NUM_BUCKETS; i++) {
+ fprintf(file, "\n Number %s: %u", JANK_TYPE_NAMES[i], mBuckets[i].count);
+ }
+ fprintf(file, "\n");
+ fflush(file);
+}
+
+void JankTracker::reset() {
+ memset(mBuckets, 0, sizeof(JankBucket) * NUM_BUCKETS);
+ mTotalFrameCount = 0;
+ mJankFrameCount = 0;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
new file mode 100644
index 0000000..aa554cd
--- /dev/null
+++ b/libs/hwui/JankTracker.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef JANKTRACKER_H_
+#define JANKTRACKER_H_
+
+#include "FrameInfo.h"
+#include "renderthread/TimeLord.h"
+#include "utils/RingBuffer.h"
+
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+enum JankType {
+ kMissedVsync = 0,
+ kHighInputLatency,
+ kSlowUI,
+ kSlowSync,
+ kSlowRT,
+
+ // must be last
+ NUM_BUCKETS,
+};
+
+struct JankBucket {
+ // Number of frames that hit this bucket
+ uint32_t count;
+};
+
+// TODO: Replace DrawProfiler with this
+class JankTracker {
+public:
+ JankTracker(nsecs_t frameIntervalNanos);
+
+ void setFrameInterval(nsecs_t frameIntervalNanos);
+
+ void addFrame(const FrameInfo& frame);
+
+ void dump(int fd);
+ void reset();
+
+private:
+ JankBucket mBuckets[NUM_BUCKETS];
+ int64_t mThresholds[NUM_BUCKETS];
+
+ int64_t mFrameInterval;
+ uint32_t mTotalFrameCount;
+ uint32_t mJankFrameCount;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* JANKTRACKER_H_ */
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 84ff021..3c1f1d1 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -200,10 +200,14 @@
return stencil;
}
- inline GLuint getTexture() const {
+ inline GLuint getTextureId() const {
return texture.id;
}
+ inline Texture& getTexture() {
+ return texture;
+ }
+
inline GLenum getRenderTarget() const {
return renderTarget;
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index b4b14e8..f598664 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -247,7 +247,7 @@
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- layer->getTexture(), 0);
+ layer->getTextureId(), 0);
renderState.bindFramebuffer(previousFbo);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 61cd16f..b62af3b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -57,30 +57,11 @@
#define EVENT_LOGD(...)
#endif
+#define USE_GLOPS true
+
namespace android {
namespace uirenderer {
-static GLenum getFilter(const SkPaint* paint) {
- if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
- return GL_LINEAR;
- }
- return GL_NEAREST;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Globals
-///////////////////////////////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Functions
-///////////////////////////////////////////////////////////////////////////////
-
-template<typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
@@ -772,7 +753,7 @@
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- layer->getTexture(), 0);
+ layer->getTextureId(), 0);
// Expand the startTiling region by 1
startTilingCurrentClip(true, true);
@@ -881,9 +862,9 @@
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(layer->getColorFilter());
if (layer->getRenderTarget() == GL_TEXTURE_2D) {
- setupDrawTexture(layer->getTexture());
+ setupDrawTexture(layer->getTextureId());
} else {
- setupDrawExternalTexture(layer->getTexture());
+ setupDrawExternalTexture(layer->getTextureId());
}
if (currentTransform()->isPureTranslate() &&
!layer->getForceFilter() &&
@@ -943,7 +924,7 @@
bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f;
drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
- layer->getTexture(), &layerPaint, blend,
+ layer->getTextureId(), &layerPaint, blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
GL_TRIANGLE_STRIP, kUnitQuadCount, swap, swap || simpleTransform);
@@ -1080,7 +1061,7 @@
setupDrawDirtyRegionsDisabled();
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(layer->getColorFilter());
- setupDrawTexture(layer->getTexture());
+ setupDrawTexture(layer->getTextureId());
if (currentTransform()->isPureTranslate()) {
const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
@@ -1204,7 +1185,7 @@
void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
GLsizei elementsCount = quadsCount * 6;
while (elementsCount > 0) {
- GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
+ GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
setupDrawIndexedVertices(&mesh[0].x);
glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr);
@@ -1217,8 +1198,8 @@
}
void OpenGLRenderer::clearLayerRegions() {
- const size_t count = mLayers.size();
- if (count == 0) return;
+ const size_t quadCount = mLayers.size();
+ if (quadCount == 0) return;
if (!mState.currentlyIgnored()) {
EVENT_LOGD("clearLayerRegions");
@@ -1231,10 +1212,10 @@
// is likely different so we need to disable clipping here
bool scissorChanged = mRenderState.scissor().setEnabled(false);
- Vertex mesh[count * 4];
+ Vertex mesh[quadCount * 4];
Vertex* vertex = mesh;
- for (uint32_t i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < quadCount; i++) {
const Rect& bounds = mLayers[i];
Vertex::set(vertex++, bounds.left, bounds.top);
@@ -1247,18 +1228,30 @@
// the same thing again
mLayers.clear();
- SkPaint clearPaint;
- clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshIndexedQuads(&mesh[0], quadCount)
+ .setFillClear()
+ .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setModelViewOffsetRect(0, 0, currentSnapshot()->getClipRect())
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ } else {
+ SkPaint clearPaint;
+ clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
- setupDraw(false);
- setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
- setupDrawBlending(&clearPaint, true);
- setupDrawProgram();
- setupDrawPureColorUniforms();
- setupDrawModelView(kModelViewMode_Translate, false,
- 0.0f, 0.0f, 0.0f, 0.0f, true);
+ setupDraw(false);
+ setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
+ setupDrawBlending(&clearPaint, true);
+ setupDrawProgram();
+ setupDrawPureColorUniforms();
+ setupDrawModelView(kModelViewMode_Translate, false,
+ 0.0f, 0.0f, 0.0f, 0.0f, true);
- issueIndexedQuadDraw(&mesh[0], count);
+ issueIndexedQuadDraw(&mesh[0], quadCount);
+ }
if (scissorChanged) mRenderState.scissor().setEnabled(true);
} else {
@@ -1410,11 +1403,11 @@
}
void OpenGLRenderer::drawRectangleList(const RectangleList& rectangleList) {
- int count = rectangleList.getTransformedRectanglesCount();
- std::vector<Vertex> rectangleVertices(count * 4);
+ int quadCount = rectangleList.getTransformedRectanglesCount();
+ std::vector<Vertex> rectangleVertices(quadCount * 4);
Rect scissorBox = rectangleList.calculateBounds();
scissorBox.snapToPixelBoundaries();
- for (int i = 0; i < count; ++i) {
+ for (int i = 0; i < quadCount; ++i) {
const TransformedRectangle& tr(rectangleList.getTransformedRectangle(i));
const Matrix4& transform = tr.getTransform();
Rect bounds = tr.getBounds();
@@ -1439,6 +1432,19 @@
mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
scissorBox.getWidth(), scissorBox.getHeight());
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4)
+ .setFillBlack()
+ .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setModelViewOffsetRect(0, 0, scissorBox)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
const SkPaint* paint = nullptr;
setupDraw();
setupDrawNoTexture();
@@ -1586,6 +1592,7 @@
// TODO: specify more clearly when a draw should dirty the layer.
// is writing to the stencil the only time we should ignore this?
dirtyLayer(glop.bounds.left, glop.bounds.top, glop.bounds.right, glop.bounds.bottom);
+ mDirty = true;
}
}
@@ -1611,7 +1618,7 @@
mSetShaderColor = false;
mColorSet = false;
- mColorA = mColorR = mColorG = mColorB = 0.0f;
+ mColor.a = mColor.r = mColor.g = mColor.b = 0.0f;
mTextureUnit = 0;
mTrackDirtyRegions = true;
@@ -1647,21 +1654,21 @@
}
void OpenGLRenderer::setupDrawColor(int color, int alpha) {
- mColorA = alpha / 255.0f;
- mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
- mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f;
- mColorB = mColorA * ((color ) & 0xFF) / 255.0f;
+ mColor.a = alpha / 255.0f;
+ mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
+ mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f;
+ mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f;
mColorSet = true;
- mSetShaderColor = mDescription.setColorModulate(mColorA);
+ mSetShaderColor = mDescription.setColorModulate(mColor.a);
}
void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
- mColorA = alpha / 255.0f;
- mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
- mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f;
- mColorB = mColorA * ((color ) & 0xFF) / 255.0f;
+ mColor.a = alpha / 255.0f;
+ mColor.r = mColor.a * ((color >> 16) & 0xFF) / 255.0f;
+ mColor.g = mColor.a * ((color >> 8) & 0xFF) / 255.0f;
+ mColor.b = mColor.a * ((color ) & 0xFF) / 255.0f;
mColorSet = true;
- mSetShaderColor = mDescription.setAlpha8ColorModulate(mColorR, mColorG, mColorB, mColorA);
+ mSetShaderColor = mDescription.setAlpha8ColorModulate(mColor.r, mColor.g, mColor.b, mColor.a);
}
void OpenGLRenderer::setupDrawTextGamma(const SkPaint* paint) {
@@ -1669,10 +1676,10 @@
}
void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
- mColorA = a;
- mColorR = r;
- mColorG = g;
- mColorB = b;
+ mColor.a = a;
+ mColor.r = r;
+ mColor.g = g;
+ mColor.b = b;
mColorSet = true;
mSetShaderColor = mDescription.setColorModulate(a);
}
@@ -1699,8 +1706,8 @@
void OpenGLRenderer::accountForClear(SkXfermode::Mode mode) {
if (mColorSet && mode == SkXfermode::kClear_Mode) {
- mColorA = 1.0f;
- mColorR = mColorG = mColorB = 0.0f;
+ mColor.a = 1.0f;
+ mColor.r = mColor.g = mColor.b = 0.0f;
mSetShaderColor = mDescription.modulate = true;
}
}
@@ -1713,7 +1720,7 @@
// TODO: check shader blending, once we have shader drawing support for layers.
bool blend = layer->isBlend()
|| getLayerAlpha(layer) < 1.0f
- || (mColorSet && mColorA < 1.0f)
+ || (mColorSet && mColor.a < 1.0f)
|| PaintUtils::isBlendedColorFilter(layer->getColorFilter());
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1723,7 +1730,7 @@
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
- blend |= (mColorSet && mColorA < 1.0f)
+ blend |= (mColorSet && mColor.a < 1.0f)
|| (getShader(paint) && !getShader(paint)->isOpaque())
|| PaintUtils::isBlendedColorFilter(getColorFilter(paint));
chooseBlending(blend, mode, mDescription, swapSrcDst);
@@ -1775,13 +1782,13 @@
void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
- mCaches.program().setColor(mColorR, mColorG, mColorB, mColorA);
+ mCaches.program().setColor(mColor);
}
}
void OpenGLRenderer::setupDrawPureColorUniforms() {
if (mSetShaderColor) {
- mCaches.program().setColor(mColorR, mColorG, mColorB, mColorA);
+ mCaches.program().setColor(mColor);
}
}
@@ -1973,22 +1980,21 @@
}
}
-void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top,
- const SkPaint* paint) {
- float x = left;
- float y = top;
+void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) {
+ float x = 0;
+ float y = 0;
texture->setWrap(GL_CLAMP_TO_EDGE, true);
bool ignoreTransform = false;
if (currentTransform()->isPureTranslate()) {
- x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
- y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
+ x = (int) floorf(currentTransform()->getTranslateX() + 0.5f);
+ y = (int) floorf(currentTransform()->getTranslateY() + 0.5f);
ignoreTransform = true;
texture->setFilter(GL_NEAREST, true);
} else {
- texture->setFilter(getFilter(paint), true);
+ texture->setFilter(PaintUtils::getFilter(paint), true);
}
// No need to check for a UV mapper on the texture object, only ARGB_8888
@@ -2013,7 +2019,7 @@
const AutoTexture autoCleanup(texture);
texture->setWrap(GL_CLAMP_TO_EDGE, true);
- texture->setFilter(pureTranslate ? GL_NEAREST : getFilter(paint), true);
+ texture->setFilter(pureTranslate ? GL_NEAREST : PaintUtils::getFilter(paint), true);
const float x = (int) floorf(bounds.left + 0.5f);
const float y = (int) floorf(bounds.top + 0.5f);
@@ -2042,10 +2048,24 @@
if (!texture) return;
const AutoTexture autoCleanup(texture);
+ if (USE_GLOPS) {
+ bool isAlpha8Texture = bitmap->colorType() == kAlpha_8_SkColorType;
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshTexturedUnitQuad(texture->uvMapper)
+ .setFillTexturePaint(*texture, isAlpha8Texture, paint, currentSnapshot()->alpha)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
if (CC_UNLIKELY(bitmap->colorType() == kAlpha_8_SkColorType)) {
- drawAlphaBitmap(texture, 0, 0, paint);
+ drawAlphaBitmap(texture, paint);
} else {
- drawTextureRect(0, 0, bitmap->width(), bitmap->height(), texture, paint);
+ drawTextureRect(texture, paint);
}
mDirty = true;
@@ -2130,7 +2150,7 @@
const AutoTexture autoCleanup(texture);
texture->setWrap(GL_CLAMP_TO_EDGE, true);
- texture->setFilter(getFilter(paint), true);
+ texture->setFilter(PaintUtils::getFilter(paint), true);
int alpha;
SkXfermode::Mode mode;
@@ -2213,10 +2233,10 @@
dstLeft = x;
dstTop = y;
- texture->setFilter(scaled ? getFilter(paint) : GL_NEAREST, true);
+ texture->setFilter(scaled ? PaintUtils::getFilter(paint) : GL_NEAREST, true);
ignoreTransform = true;
} else {
- texture->setFilter(getFilter(paint), true);
+ texture->setFilter(PaintUtils::getFilter(paint), true);
}
if (CC_UNLIKELY(useScaleTransform)) {
@@ -2350,15 +2370,16 @@
return;
}
- if (!paint->getShader() && !currentSnapshot()->roundRectClipState) {
+ if (USE_GLOPS) {
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
bool fudgeOffset = displayFlags & kVertexBuffer_Offset;
bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
aBuilder.setMeshVertexBuffer(vertexBuffer, shadowInterp)
+ .setFillPaint(*paint, currentSnapshot()->alpha)
.setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
.setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
- .setPaint(*paint, currentSnapshot()->alpha)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
renderGlop(glop);
return;
@@ -2496,7 +2517,7 @@
mDirty = true;
}
-void OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture,
+void OpenGLRenderer::drawShape(float left, float top, PathTexture* texture,
const SkPaint* paint) {
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -2519,7 +2540,7 @@
if (p->getPathEffect() != nullptr) {
mCaches.textureState().activateTexture(0);
- const PathTexture* texture = mCaches.pathCache.getRoundRect(
+ PathTexture* texture = mCaches.pathCache.getRoundRect(
right - left, bottom - top, rx, ry, p);
drawShape(left, top, texture, p);
} else {
@@ -2537,7 +2558,7 @@
}
if (p->getPathEffect() != nullptr) {
mCaches.textureState().activateTexture(0);
- const PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
+ PathTexture* texture = mCaches.pathCache.getCircle(radius, p);
drawShape(x - radius, y - radius, texture, p);
} else {
SkPath path;
@@ -2560,7 +2581,7 @@
if (p->getPathEffect() != nullptr) {
mCaches.textureState().activateTexture(0);
- const PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
+ PathTexture* texture = mCaches.pathCache.getOval(right - left, bottom - top, p);
drawShape(left, top, texture, p);
} else {
SkPath path;
@@ -2584,7 +2605,7 @@
// TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != nullptr || useCenter) {
mCaches.textureState().activateTexture(0);
- const PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
+ PathTexture* texture = mCaches.pathCache.getArc(right - left, bottom - top,
startAngle, sweepAngle, useCenter, p);
drawShape(left, top, texture, p);
return;
@@ -2621,7 +2642,7 @@
if (p->getPathEffect() != nullptr || p->getStrokeJoin() != SkPaint::kMiter_Join ||
p->getStrokeMiter() != SkPaintDefaults_MiterLimit) {
mCaches.textureState().activateTexture(0);
- const PathTexture* texture =
+ PathTexture* texture =
mCaches.pathCache.getRect(right - left, bottom - top, p);
drawShape(left, top, texture, p);
} else {
@@ -2659,17 +2680,30 @@
// NOTE: The drop shadow will not perform gamma correction
// if shader-based correction is enabled
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
- const ShadowTexture* shadow = mCaches.dropShadowCache.get(
+ ShadowTexture* texture = mCaches.dropShadowCache.get(
paint, text, bytesCount, count, textShadow.radius, positions);
// If the drop shadow exceeds the max texture size or couldn't be
// allocated, skip drawing
- if (!shadow) return;
- const AutoTexture autoCleanup(shadow);
+ if (!texture) return;
+ const AutoTexture autoCleanup(texture);
- const float sx = x - shadow->left + textShadow.dx;
- const float sy = y - shadow->top + textShadow.dy;
+ const float sx = x - texture->left + textShadow.dx;
+ const float sy = y - texture->top + textShadow.dy;
- const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * writableSnapshot()->alpha;
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshTexturedUnitQuad(nullptr)
+ .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
+ const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * currentSnapshot()->alpha;
if (getShader(paint)) {
textShadow.color = SK_ColorWHITE;
}
@@ -2682,8 +2716,8 @@
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
- sx, sy, sx + shadow->width, sy + shadow->height);
- setupDrawTexture(shadow->id);
+ sx, sy, sx + texture->width, sy + texture->height);
+ setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms(getShader(paint));
@@ -2965,7 +2999,7 @@
mCaches.textureState().activateTexture(0);
- const PathTexture* texture = mCaches.pathCache.get(path, paint);
+ PathTexture* texture = mCaches.pathCache.get(path, paint);
if (!texture) return;
const AutoTexture autoCleanup(texture);
@@ -3015,46 +3049,58 @@
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
composeLayerRect(layer, layer->regionRect));
} else if (layer->mesh) {
-
- const float a = getLayerAlpha(layer);
- setupDraw();
- setupDrawWithTexture();
- setupDrawColor(a, a, a, a);
- setupDrawColorFilter(layer->getColorFilter());
- setupDrawBlending(layer);
- setupDrawProgram();
- setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms(layer->getColorFilter());
- setupDrawTexture(layer->getTexture());
- if (CC_LIKELY(currentTransform()->isPureTranslate())) {
- int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
- int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
-
- layer->setFilter(GL_NEAREST);
- setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
- tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
+ .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode())
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
} else {
- layer->setFilter(GL_LINEAR);
- setupDrawModelView(kModelViewMode_Translate, false, x, y,
- x + layer->layer.getWidth(), y + layer->layer.getHeight());
+ const float a = getLayerAlpha(layer);
+ setupDraw();
+ setupDrawWithTexture();
+ setupDrawColor(a, a, a, a);
+ setupDrawColorFilter(layer->getColorFilter());
+ setupDrawBlending(layer);
+ setupDrawProgram();
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms(layer->getColorFilter());
+ setupDrawTexture(layer->getTextureId());
+ if (CC_LIKELY(currentTransform()->isPureTranslate())) {
+ int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
+ int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
+
+ layer->setFilter(GL_NEAREST);
+ setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
+ tx + layer->layer.getWidth(), ty + layer->layer.getHeight(), true);
+ } else {
+ layer->setFilter(GL_LINEAR);
+ setupDrawModelView(kModelViewMode_Translate, false, x, y,
+ x + layer->layer.getWidth(), y + layer->layer.getHeight());
+ }
+
+
+ TextureVertex* mesh = &layer->mesh[0];
+ GLsizei elementsCount = layer->meshElementCount;
+
+
+ while (elementsCount > 0) {
+ GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
+
+ setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
+ DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
+ glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr));
+
+ elementsCount -= drawCount;
+ // Though there are 4 vertices in a quad, we use 6 indices per
+ // quad to draw with GL_TRIANGLES
+ mesh += (drawCount / 6) * 4;
+ }
}
-
- TextureVertex* mesh = &layer->mesh[0];
- GLsizei elementsCount = layer->meshElementCount;
-
- while (elementsCount > 0) {
- GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
-
- setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
- DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
- glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr));
-
- elementsCount -= drawCount;
- // Though there are 4 vertices in a quad, we use 6 indices per
- // quad to draw with GL_TRIANGLES
- mesh += (drawCount / 6) * 4;
- }
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRectsDebug(layer->region);
#endif
@@ -3098,12 +3144,26 @@
return texture;
}
-void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
- float x, float y, const SkPaint* paint) {
+void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y,
+ const SkPaint* paint) {
if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) {
return;
}
+ if (USE_GLOPS) {
+ Glop glop;
+ GlopBuilder aBuilder(mRenderState, mCaches, &glop);
+ aBuilder.setMeshTexturedUnitQuad(nullptr)
+ .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
+ .build();
+ renderGlop(glop);
+ return;
+ }
+
+
int alpha;
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
@@ -3251,14 +3311,15 @@
return;
}
- if (!paint->getShader() && !currentSnapshot()->roundRectClipState) {
+ if (USE_GLOPS) {
const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshIndexedQuads(&mesh[0], count / 4)
+ .setFillPaint(*paint, currentSnapshot()->alpha)
.setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
.setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
- .setPaint(*paint, currentSnapshot()->alpha)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
renderGlop(glop);
return;
@@ -3296,14 +3357,15 @@
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
const SkPaint* paint, bool ignoreTransform) {
- if (!paint->getShader() && !currentSnapshot()->roundRectClipState) {
+ if (USE_GLOPS) {
const Matrix4& transform = ignoreTransform ? Matrix4::identity() : *currentTransform();
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshUnitQuad()
+ .setFillPaint(*paint, currentSnapshot()->alpha)
.setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
.setModelViewMapUnitToRect(Rect(left, top, right, bottom))
- .setPaint(*paint, currentSnapshot()->alpha)
+ .setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
renderGlop(glop);
return;
@@ -3332,8 +3394,7 @@
glDrawArrays(GL_TRIANGLE_STRIP, 0, kUnitQuadCount);
}
-void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
- Texture* texture, const SkPaint* paint) {
+void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) {
texture->setWrap(GL_CLAMP_TO_EDGE, true);
GLvoid* vertices = (GLvoid*) nullptr;
@@ -3350,16 +3411,16 @@
}
if (CC_LIKELY(currentTransform()->isPureTranslate())) {
- const float x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
- const float y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
+ const float x = (int) floorf(currentTransform()->getTranslateX() + 0.5f);
+ const float y = (int) floorf(currentTransform()->getTranslateY() + 0.5f);
texture->setFilter(GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
paint, texture->blend, vertices, texCoords,
GL_TRIANGLE_STRIP, kUnitQuadCount, false, true);
} else {
- texture->setFilter(getFilter(paint), true);
- drawTextureMesh(left, top, right, bottom, texture->id, paint,
+ texture->setFilter(PaintUtils::getFilter(paint), true);
+ drawTextureMesh(0, 0, texture->width, texture->height, texture->id, paint,
texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kUnitQuadCount);
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f097041..851effa5 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -690,18 +690,16 @@
* @param texture The texture reprsenting the shape
* @param paint The paint to draw the shape with
*/
- void drawShape(float left, float top, const PathTexture* texture, const SkPaint* paint);
+ void drawShape(float left, float top, PathTexture* texture, const SkPaint* paint);
/**
* Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
* different compositing rules.
*
* @param texture The texture to draw with
- * @param left The x coordinate of the bitmap
- * @param top The y coordinate of the bitmap
* @param paint The paint to render with
*/
- void drawAlphaBitmap(Texture* texture, float left, float top, const SkPaint* paint);
+ void drawAlphaBitmap(Texture* texture, const SkPaint* paint);
/**
* Renders a strip of polygons with the specified paint, used for tessellated geometry.
@@ -730,18 +728,12 @@
void drawConvexPath(const SkPath& path, const SkPaint* paint);
/**
- * Draws a textured rectangle with the specified texture. The specified coordinates
- * are transformed by the current snapshot's transform matrix.
+ * Draws a textured rectangle with the specified texture.
*
- * @param left The left coordinate of the rectangle
- * @param top The top coordinate of the rectangle
- * @param right The right coordinate of the rectangle
- * @param bottom The bottom coordinate of the rectangle
* @param texture The texture to use
* @param paint The paint containing the alpha, blending mode, etc.
*/
- void drawTextureRect(float left, float top, float right, float bottom,
- Texture* texture, const SkPaint* paint);
+ void drawTextureRect(Texture* texture, const SkPaint* paint);
/**
* Draws a textured mesh with the specified texture. If the indices are omitted,
@@ -827,7 +819,7 @@
* @param y The y coordinate where the texture will be drawn
* @param paint The paint to draw the texture with
*/
- void drawPathTexture(const PathTexture* texture, float x, float y, const SkPaint* paint);
+ void drawPathTexture(PathTexture* texture, float x, float y, const SkPaint* paint);
/**
* Resets the texture coordinates stored in mMeshVertices. Setting the values
@@ -1010,7 +1002,7 @@
ProgramDescription mDescription;
// Color description
bool mColorSet;
- float mColorA, mColorR, mColorG, mColorB;
+ FloatColor mColor;
// Indicates that the shader should get a color
bool mSetShaderColor;
// Current texture unit
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 5f34b34..32713e9b 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -177,12 +177,12 @@
glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]);
}
-void Program::setColor(const float r, const float g, const float b, const float a) {
+void Program::setColor(FloatColor color) {
if (!mHasColorUniform) {
mColorUniform = getUniform("color");
mHasColorUniform = true;
}
- glUniform4f(mColorUniform, r, g, b, a);
+ glUniform4f(mColorUniform, color.r, color.g, color.b, color.a);
}
void Program::use() {
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 01231b5..af1e4a7 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -25,6 +25,7 @@
#include <SkXfermode.h>
#include "Debug.h"
+#include "FloatColor.h"
#include "Matrix.h"
#include "Properties.h"
@@ -363,7 +364,7 @@
/**
* Sets the color associated with this shader.
*/
- void setColor(const float r, const float g, const float b, const float a);
+ void setColor(FloatColor color);
/**
* Name of the texCoords attribute if it exists (kBindingTexCoords), -1 otherwise.
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 659ef6c..c6fdd3f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -402,9 +402,10 @@
clipFlags = 0; // all clipping done by saveLayer
}
- ATRACE_FORMAT("%s alpha caused %ssaveLayer %dx%d",
- getName(), clipFlags ? "" : "unclipped ",
- (int)layerBounds.getWidth(), (int)layerBounds.getHeight());
+ ATRACE_FORMAT("%s alpha caused %ssaveLayer %dx%d", getName(),
+ (saveFlags & SkCanvas::kClipToLayer_SaveFlag) ? "" : "unclipped ",
+ static_cast<int>(layerBounds.getWidth()),
+ static_cast<int>(layerBounds.getHeight()));
SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
layerBounds.left, layerBounds.top, layerBounds.right, layerBounds.bottom,
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index ca7f48d..9509c48 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -87,8 +87,8 @@
reverseReceiverTransform.loadInverse(receiverTransform);
reverseReceiverTransform.mapPoint3d(adjustedLightCenter);
- if (CC_UNLIKELY(caches.propertyLightDiameter > 0)) {
- lightRadius = caches.propertyLightDiameter;
+ if (CC_UNLIKELY(caches.propertyLightRadius > 0)) {
+ lightRadius = caches.propertyLightRadius;
}
// Now light and caster are both in local space, we will check whether
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index de5f91c..3c65705 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -228,21 +228,23 @@
}
// setup the first glyph position and adjust bounds if needed
+ int xBaseline = 0;
+ int yBaseline = 0;
if (mCanvas->drawTextAbsolutePos()) {
bounds.offset(x,y);
- pointStorage[0].set(x, y);
- } else {
- pointStorage[0].set(0, 0);
+ xBaseline = x;
+ yBaseline = y;
}
+ pointStorage[0].set(xBaseline, yBaseline);
// setup the remaining glyph positions
if (glyphs.paint.isVerticalText()) {
for (int i = 1; i < glyphs.count; i++) {
- pointStorage[i].set(x, glyphWidths[i-1] + pointStorage[i-1].fY);
+ pointStorage[i].set(xBaseline, glyphWidths[i-1] + pointStorage[i-1].fY);
}
} else {
for (int i = 1; i < glyphs.count; i++) {
- pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, y);
+ pointStorage[i].set(glyphWidths[i-1] + pointStorage[i-1].fX, yBaseline);
}
}
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 9c929da..2fcf7f3 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -16,17 +16,17 @@
#define LOG_TAG "OpenGLRenderer"
-#include <utils/Log.h>
-
-#include <SkMatrix.h>
+#include "SkiaShader.h"
#include "Caches.h"
#include "Extensions.h"
#include "Layer.h"
#include "Matrix.h"
-#include "SkiaShader.h"
#include "Texture.h"
+#include <SkMatrix.h>
+#include <utils/Log.h>
+
namespace android {
namespace uirenderer {
@@ -34,7 +34,7 @@
// Support
///////////////////////////////////////////////////////////////////////////////
-static const GLint gTileModes[] = {
+static const GLenum gTileModes[] = {
GL_CLAMP_TO_EDGE, // == SkShader::kClamp_TileMode
GL_REPEAT, // == SkShader::kRepeat_Mode
GL_MIRRORED_REPEAT // == SkShader::kMirror_TileMode
@@ -56,6 +56,10 @@
a);
}
+static inline void bindUniformColor(int slot, FloatColor color) {
+ glUniform4fv(slot, 1, reinterpret_cast<const float*>(&color));
+}
+
static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
caches->textureState().bindTexture(texture->id);
texture->setWrapST(wrapS, wrapT);
@@ -270,7 +274,7 @@
}
GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().textureState().activateTexture(textureSlot);
+ caches->textureState().activateTexture(textureSlot);
BitmapShaderInfo shaderInfo;
if (!bitmapShaderHelper(caches, nullptr, &shaderInfo, extensions, bitmap, xy)) {
@@ -470,5 +474,290 @@
SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
}
+///////////////////////////////////////////////////////////////////////////////
+// Store / apply
+///////////////////////////////////////////////////////////////////////////////
+
+bool tryStoreGradient(Caches& caches, const SkShader& shader, const Matrix4 modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData::GradientShaderData* outData) {
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = 0;
+ gradInfo.fColors = nullptr;
+ gradInfo.fColorOffsets = nullptr;
+
+ SkMatrix unitMatrix;
+ switch (shader.asAGradient(&gradInfo)) {
+ case SkShader::kLinear_GradientType:
+ description->gradientType = ProgramDescription::kGradientLinear;
+
+ toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+ break;
+ case SkShader::kRadial_GradientType:
+ description->gradientType = ProgramDescription::kGradientCircular;
+
+ toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
+ gradInfo.fRadius[0], &unitMatrix);
+ break;
+ case SkShader::kSweep_GradientType:
+ description->gradientType = ProgramDescription::kGradientSweep;
+
+ toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
+ break;
+ default:
+ // Do nothing. This shader is unsupported.
+ return false;
+ }
+ description->hasGradient = true;
+ description->isSimpleGradient = isSimpleGradient(gradInfo);
+
+ computeScreenSpaceMatrix(outData->screenSpace, unitMatrix,
+ shader.getLocalMatrix(), modelViewMatrix);
+
+ // re-query shader to get full color / offset data
+ std::unique_ptr<SkColor[]> colorStorage(new SkColor[gradInfo.fColorCount]);
+ std::unique_ptr<SkScalar[]> colorOffsets(new SkScalar[gradInfo.fColorCount]);
+ gradInfo.fColors = &colorStorage[0];
+ gradInfo.fColorOffsets = &colorOffsets[0];
+ shader.asAGradient(&gradInfo);
+
+ if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
+ outData->gradientSampler = (*textureUnit)++;
+
+#ifndef SK_SCALAR_IS_FLOAT
+ #error Need to convert gradInfo.fColorOffsets to float!
+#endif
+ outData->gradientTexture = caches.gradientCache.get(
+ gradInfo.fColors, gradInfo.fColorOffsets, gradInfo.fColorCount);
+ outData->wrapST = gTileModes[gradInfo.fTileMode];
+ } else {
+ outData->gradientSampler = 0;
+ outData->gradientTexture = nullptr;
+
+ outData->startColor.set(gradInfo.fColors[0]);
+ outData->endColor.set(gradInfo.fColors[1]);
+ }
+
+ outData->ditherSampler = (*textureUnit)++;
+ return true;
+}
+
+void applyGradient(Caches& caches, const SkiaShaderData::GradientShaderData& data) {
+ if (CC_UNLIKELY(data.gradientTexture)) {
+ caches.textureState().activateTexture(data.gradientSampler);
+ bindTexture(&caches, data.gradientTexture, data.wrapST, data.wrapST);
+ glUniform1i(caches.program().getUniform("gradientSampler"), data.gradientSampler);
+ } else {
+ bindUniformColor(caches.program().getUniform("startColor"), data.startColor);
+ bindUniformColor(caches.program().getUniform("endColor"), data.endColor);
+ }
+
+ // TODO: remove sampler slot incrementing from dither.setupProgram,
+ // since this assignment of slots is done at store, not apply time
+ GLuint ditherSampler = data.ditherSampler;
+ caches.dither.setupProgram(caches.program(), &ditherSampler);
+ glUniformMatrix4fv(caches.program().getUniform("screenSpace"), 1,
+ GL_FALSE, &data.screenSpace.data[0]);
+}
+
+bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData::BitmapShaderData* outData) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
+ return false;
+ }
+
+ outData->bitmapTexture = caches.textureCache.get(&bitmap);
+ if (!outData->bitmapTexture) return false;
+
+ outData->bitmapSampler = (*textureUnit)++;
+
+ const float width = outData->bitmapTexture->width;
+ const float height = outData->bitmapTexture->height;
+
+ description->hasBitmap = true;
+ if (!caches.extensions().hasNPot()
+ && (!isPowerOfTwo(width) || !isPowerOfTwo(height))
+ && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode)) {
+ description->isBitmapNpot = true;
+ description->bitmapWrapS = gTileModes[xy[0]];
+ description->bitmapWrapT = gTileModes[xy[1]];
+
+ outData->wrapS = GL_CLAMP_TO_EDGE;
+ outData->wrapT = GL_CLAMP_TO_EDGE;
+ } else {
+ outData->wrapS = gTileModes[xy[0]];
+ outData->wrapT = gTileModes[xy[1]];
+ }
+
+ computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
+ outData->textureDimension[0] = 1.0f / width;
+ outData->textureDimension[1] = 1.0f / height;
+
+ return true;
+}
+
+void applyBitmap(Caches& caches, const SkiaShaderData::BitmapShaderData& data) {
+ caches.textureState().activateTexture(data.bitmapSampler);
+ bindTexture(&caches, data.bitmapTexture, data.wrapS, data.wrapT);
+ data.bitmapTexture->setFilter(GL_LINEAR);
+
+ glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
+ glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1, GL_FALSE,
+ &data.textureTransform.data[0]);
+ glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
+}
+
+SkiaShaderType getComposeSubType(const SkShader& shader) {
+ // First check for a gradient shader.
+ switch (shader.asAGradient(nullptr)) {
+ case SkShader::kNone_GradientType:
+ // Not a gradient shader. Fall through to check for other types.
+ break;
+ case SkShader::kLinear_GradientType:
+ case SkShader::kRadial_GradientType:
+ case SkShader::kSweep_GradientType:
+ return kGradient_SkiaShaderType;
+ default:
+ // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
+ return kNone_SkiaShaderType;
+ }
+
+ // The shader is not a gradient. Check for a bitmap shader.
+ if (shader.asABitmap(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) {
+ return kBitmap_SkiaShaderType;
+ }
+ return kNone_SkiaShaderType;
+}
+
+void storeCompose(Caches& caches, const SkShader& bitmapShader, const SkShader& gradientShader,
+ const Matrix4& modelViewMatrix, GLuint* textureUnit,
+ ProgramDescription* description, SkiaShaderData* outData) {
+ LOG_ALWAYS_FATAL_IF(!tryStoreBitmap(caches, bitmapShader, modelViewMatrix,
+ textureUnit, description, &outData->bitmapData),
+ "failed storing bitmap shader data");
+ LOG_ALWAYS_FATAL_IF(!tryStoreGradient(caches, gradientShader, modelViewMatrix,
+ textureUnit, description, &outData->gradientData),
+ "failing storing gradient shader data");
+}
+
+bool tryStoreCompose(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData) {
+
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) return false;
+
+ const SkiaShaderType shaderAType = getComposeSubType(*rec.fShaderA);
+ const SkiaShaderType shaderBType = getComposeSubType(*rec.fShaderB);
+
+ // check that type enum values are the 2 flags that compose the kCompose value
+ if ((shaderAType & shaderBType) != 0) return false;
+ if ((shaderAType | shaderBType) != kCompose_SkiaShaderType) return false;
+
+ mat4 transform;
+ computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(), modelViewMatrix);
+ if (shaderAType == kBitmap_SkiaShaderType) {
+ description->isBitmapFirst = true;
+ storeCompose(caches, *rec.fShaderA, *rec.fShaderB,
+ transform, textureUnit, description, outData);
+ } else {
+ description->isBitmapFirst = false;
+ storeCompose(caches, *rec.fShaderB, *rec.fShaderA,
+ transform, textureUnit, description, outData);
+ }
+ if (!SkXfermode::AsMode(rec.fMode, &description->shadersMode)) {
+ // TODO: Support other modes.
+ description->shadersMode = SkXfermode::kSrcOver_Mode;
+ }
+ return true;
+}
+
+bool tryStoreLayer(Caches& caches, const SkShader& shader, const Matrix4& modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData::LayerShaderData* outData) {
+ Layer* layer;
+ if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
+ return false;
+ }
+
+ description->hasBitmap = true;
+ outData->layer = layer;
+ outData->bitmapSampler = (*textureUnit)++;
+
+ const float width = layer->getWidth();
+ const float height = layer->getHeight();
+
+ computeScreenSpaceMatrix(outData->textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
+
+ outData->textureDimension[0] = 1.0f / width;
+ outData->textureDimension[1] = 1.0f / height;
+ return true;
+}
+
+void applyLayer(Caches& caches, const SkiaShaderData::LayerShaderData& data) {
+ caches.textureState().activateTexture(data.bitmapSampler);
+
+ data.layer->bindTexture();
+ data.layer->setWrap(GL_CLAMP_TO_EDGE);
+ data.layer->setFilter(GL_LINEAR);
+
+ glUniform1i(caches.program().getUniform("bitmapSampler"), data.bitmapSampler);
+ glUniformMatrix4fv(caches.program().getUniform("textureTransform"), 1,
+ GL_FALSE, &data.textureTransform.data[0]);
+ glUniform2fv(caches.program().getUniform("textureDimension"), 1, &data.textureDimension[0]);
+}
+
+void SkiaShader::store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData) {
+ if (!shader) {
+ outData->skiaShaderType = kNone_SkiaShaderType;
+ return;
+ }
+
+ if (tryStoreGradient(caches, *shader, modelViewMatrix,
+ textureUnit, description, &outData->gradientData)) {
+ outData->skiaShaderType = kGradient_SkiaShaderType;
+ return;
+ }
+
+ if (tryStoreBitmap(caches, *shader, modelViewMatrix,
+ textureUnit, description, &outData->bitmapData)) {
+ outData->skiaShaderType = kBitmap_SkiaShaderType;
+ return;
+ }
+
+ if (tryStoreCompose(caches, *shader, modelViewMatrix,
+ textureUnit, description, outData)) {
+ outData->skiaShaderType = kCompose_SkiaShaderType;
+ return;
+ }
+
+ if (tryStoreLayer(caches, *shader, modelViewMatrix,
+ textureUnit, description, &outData->layerData)) {
+ outData->skiaShaderType = kLayer_SkiaShaderType;
+ }
+}
+
+void SkiaShader::apply(Caches& caches, const SkiaShaderData& data) {
+ if (!data.skiaShaderType) return;
+
+ if (data.skiaShaderType & kGradient_SkiaShaderType) {
+ applyGradient(caches, data.gradientData);
+ }
+ if (data.skiaShaderType & kBitmap_SkiaShaderType) {
+ applyBitmap(caches, data.bitmapData);
+ }
+
+ if (data.skiaShaderType == kLayer_SkiaShaderType) {
+ applyLayer(caches, data.layerData);
+ }
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index e110ca5..2962441c 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -17,32 +17,72 @@
#ifndef ANDROID_HWUI_SKIA_SHADER_H
#define ANDROID_HWUI_SKIA_SHADER_H
-#include <SkShader.h>
-#include <SkXfermode.h>
+#include "FloatColor.h"
+#include "Matrix.h"
#include <GLES2/gl2.h>
-
+#include <SkShader.h>
+#include <SkXfermode.h>
#include <cutils/compiler.h>
-#include "Matrix.h"
-
namespace android {
namespace uirenderer {
class Caches;
class Extensions;
class Layer;
+class Texture;
struct ProgramDescription;
/**
* Type of Skia shader in use.
+ *
+ * Note that kBitmap | kGradient = kCompose, since Compose implies
+ * both its component types are in use simultaneously. No other
+ * composition of multiple types is supported.
*/
enum SkiaShaderType {
- kNone_SkiaShaderType,
- kBitmap_SkiaShaderType,
- kGradient_SkiaShaderType,
- kCompose_SkiaShaderType,
- kLayer_SkiaShaderType
+ kNone_SkiaShaderType = 0,
+ kBitmap_SkiaShaderType = 1,
+ kGradient_SkiaShaderType = 2,
+ kCompose_SkiaShaderType = kBitmap_SkiaShaderType | kGradient_SkiaShaderType,
+ kLayer_SkiaShaderType = 4,
+};
+
+struct SkiaShaderData {
+ SkiaShaderType skiaShaderType;
+ struct BitmapShaderData {
+ Texture* bitmapTexture;
+ GLuint bitmapSampler;
+ GLenum wrapS;
+ GLenum wrapT;
+
+ Matrix4 textureTransform;
+ float textureDimension[2];
+ } bitmapData;
+ struct GradientShaderData {
+ Matrix4 screenSpace;
+ GLuint ditherSampler;
+
+ // simple gradient
+ FloatColor startColor;
+ FloatColor endColor;
+
+ // complex gradient
+ Texture* gradientTexture;
+ GLuint gradientSampler;
+ GLenum wrapST;
+
+ } gradientData;
+ struct LayerShaderData {
+ Layer* layer;
+ GLuint bitmapSampler;
+ GLenum wrapS;
+ GLenum wrapT;
+
+ Matrix4 textureTransform;
+ float textureDimension[2];
+ } layerData;
};
class SkiaShader {
@@ -52,6 +92,12 @@
const Extensions& extensions, const SkShader& shader);
static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+
+ // new SkiaShader interaction model - store into ShaderData, and apply to Caches/Program/GL
+ static void store(Caches& caches, const SkShader* shader, const Matrix4& modelViewMatrix,
+ GLuint* textureUnit, ProgramDescription* description,
+ SkiaShaderData* outData);
+ static void apply(Caches& caches, const SkiaShaderData& data);
};
class InvalidSkiaShader {
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 512f5cf..593e918 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -24,46 +24,6 @@
namespace android {
namespace uirenderer {
-Texture::Texture()
- : id(0)
- , generation(0)
- , blend(false)
- , width(0)
- , height(0)
- , cleanup(false)
- , bitmapSize(0)
- , mipMap(false)
- , uvMapper(nullptr)
- , isInUse(false)
- , mWrapS(GL_CLAMP_TO_EDGE)
- , mWrapT(GL_CLAMP_TO_EDGE)
- , mMinFilter(GL_NEAREST)
- , mMagFilter(GL_NEAREST)
- , mFirstFilter(true)
- , mFirstWrap(true)
- , mCaches(Caches::getInstance()) {
-}
-
-Texture::Texture(Caches& caches)
- : id(0)
- , generation(0)
- , blend(false)
- , width(0)
- , height(0)
- , cleanup(false)
- , bitmapSize(0)
- , mipMap(false)
- , uvMapper(nullptr)
- , isInUse(false)
- , mWrapS(GL_CLAMP_TO_EDGE)
- , mWrapT(GL_CLAMP_TO_EDGE)
- , mMinFilter(GL_NEAREST)
- , mMagFilter(GL_NEAREST)
- , mFirstFilter(true)
- , mFirstWrap(true)
- , mCaches(caches) {
-}
-
void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force,
GLenum renderTarget) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d5601f8..dfec462 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -30,8 +30,7 @@
*/
class Texture {
public:
- Texture();
- Texture(Caches& caches);
+ Texture(Caches& caches) : mCaches(caches) { }
virtual ~Texture() { }
@@ -59,62 +58,62 @@
/**
* Name of the texture.
*/
- GLuint id;
+ GLuint id = 0;
/**
* Generation of the backing bitmap,
*/
- uint32_t generation;
+ uint32_t generation = 0;
/**
* Indicates whether the texture requires blending.
*/
- bool blend;
+ bool blend = false;
/**
* Width of the backing bitmap.
*/
- uint32_t width;
+ uint32_t width = 0;
/**
* Height of the backing bitmap.
*/
- uint32_t height;
+ uint32_t height = 0;
/**
* Indicates whether this texture should be cleaned up after use.
*/
- bool cleanup;
+ bool cleanup= false;
/**
* Optional, size of the original bitmap.
*/
- uint32_t bitmapSize;
+ uint32_t bitmapSize = 0;
/**
* Indicates whether this texture will use trilinear filtering.
*/
- bool mipMap;
+ bool mipMap = false;
/**
* Optional, pointer to a texture coordinates mapper.
*/
- const UvMapper* uvMapper;
+ const UvMapper* uvMapper = nullptr;
/**
* Whether or not the Texture is marked in use and thus not evictable for
* the current frame. This is reset at the start of a new frame.
*/
- bool isInUse;
+ bool isInUse = false;
private:
/**
- * Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
+ * Last wrap modes set on this texture.
*/
- GLenum mWrapS;
- GLenum mWrapT;
+ GLenum mWrapS = GL_CLAMP_TO_EDGE;
+ GLenum mWrapT = GL_CLAMP_TO_EDGE;
/**
- * Last filters set on this texture. Defaults to GL_NEAREST.
+ * Last filters set on this texture.
*/
- GLenum mMinFilter;
- GLenum mMagFilter;
+ GLenum mMinFilter = GL_NEAREST;
+ GLenum mMagFilter = GL_NEAREST;
- bool mFirstFilter;
- bool mFirstWrap;
+ bool mFirstFilter = true;
+ bool mFirstWrap = true;
Caches& mCaches;
}; // struct Texture
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index f4f8e44..b911a0f 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -168,7 +168,7 @@
}
if (canCache) {
- texture = new Texture();
+ texture = new Texture(Caches::getInstance());
texture->bitmapSize = size;
generateTexture(bitmap, texture, false);
@@ -206,7 +206,7 @@
}
const uint32_t size = bitmap->rowBytes() * bitmap->height();
- texture = new Texture();
+ texture = new Texture(Caches::getInstance());
texture->bitmapSize = size;
generateTexture(bitmap, texture, false);
texture->cleanup = true;
@@ -216,7 +216,7 @@
}
Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
- Texture* texture = new Texture();
+ Texture* texture = new Texture(Caches::getInstance());
texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
texture->cleanup = true;
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index 5b80bbd..11d0c4b 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -19,11 +19,7 @@
#include "Vector.h"
-#include <type_traits>
-
-#define REQUIRE_COMPATIBLE_LAYOUT(TARGET_TYPE) \
- static_assert(std::is_standard_layout<TARGET_TYPE>::value, \
- #TARGET_TYPE " must have standard layout")
+#include "utils/Macros.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index c751dba..789f6cc 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -119,7 +119,7 @@
mEnabled = true;
}
- if (srcMode != mSrcMode || dstMode != mSrcMode) {
+ if (srcMode != mSrcMode || dstMode != mDstMode) {
glBlendFunc(srcMode, dstMode);
mSrcMode = srcMode;
mDstMode = dstMode;
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 585fb86..6b00020 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -68,6 +68,7 @@
void MeshState::dump() {
ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
+ ALOGD("MeshState IBOs: quadList %d, current %d", mQuadListIndices, mCurrentIndicesBuffer);
ALOGD("MeshState vertices: vertex data %p, stride %d",
mCurrentPositionPointer, mCurrentPositionStride);
ALOGD("MeshState texCoord: data %p, stride %d",
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 6394dc1..192bf81 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -209,23 +209,25 @@
void RenderState::render(const Glop& glop) {
const Glop::Mesh& mesh = glop.mesh;
- const Glop::Fill& shader = glop.fill;
+ const Glop::Fill& fill = glop.fill;
- // --------------------------------------------
- // ---------- Shader + uniform setup ----------
- // --------------------------------------------
- mCaches->setProgram(shader.program);
+ // ---------------------------------------------
+ // ---------- Program + uniform setup ----------
+ // ---------------------------------------------
+ mCaches->setProgram(fill.program);
- Glop::FloatColor color = shader.color;
- shader.program->setColor(color.r, color.g, color.b, color.a);
+ if (fill.colorEnabled) {
+ fill.program->setColor(fill.color);
+ }
- shader.program->set(glop.transform.ortho,
+ fill.program->set(glop.transform.ortho,
glop.transform.modelView,
glop.transform.canvas,
glop.transform.fudgingOffset);
+ // Color filter uniforms
if (glop.fill.filterMode == ProgramDescription::kColorBlend) {
- const Glop::FloatColor& color = glop.fill.filter.color;
+ const FloatColor& color = glop.fill.filter.color;
glUniform4f(mCaches->program().getUniform("colorBlend"),
color.r, color.g, color.b, color.a);
} else if (glop.fill.filterMode == ProgramDescription::kColorMatrix) {
@@ -235,11 +237,27 @@
glop.fill.filter.matrix.vector);
}
+ // Round rect clipping uniforms
+ if (glop.roundRectClipState) {
+ // TODO: avoid query, and cache values (or RRCS ptr) in program
+ const RoundRectClipState* state = glop.roundRectClipState;
+ const Rect& innerRect = state->innerRect;
+ glUniform4f(fill.program->getUniform("roundRectInnerRectLTRB"),
+ innerRect.left, innerRect.top,
+ innerRect.right, innerRect.bottom);
+ glUniformMatrix4fv(fill.program->getUniform("roundRectInvTransform"),
+ 1, GL_FALSE, &state->matrix.data[0]);
+
+ // add half pixel to round out integer rect space to cover pixel centers
+ float roundedOutRadius = state->radius + 0.5f;
+ glUniform1f(fill.program->getUniform("roundRectRadius"),
+ roundedOutRadius);
+ }
// --------------------------------
// ---------- Mesh setup ----------
// --------------------------------
// vertices
- bool force = meshState().bindMeshBufferInternal(mesh.vertexBufferObject)
+ const bool force = meshState().bindMeshBufferInternal(mesh.vertexBufferObject)
|| (mesh.vertices != nullptr);
meshState().bindPositionVertexPointer(force, mesh.vertices, mesh.stride);
@@ -247,23 +265,37 @@
meshState().bindIndicesBufferInternal(mesh.indexBufferObject);
if (mesh.vertexFlags & kTextureCoord_Attrib) {
- // TODO: support textures
- LOG_ALWAYS_FATAL("textures not yet supported");
+ // glop.fill.texture always takes slot 0, shader samplers increment from there
+ mCaches->textureState().activateTexture(0);
+
+ if (glop.fill.texture.clamp != GL_INVALID_ENUM) {
+ glop.fill.texture.texture->setWrap(glop.fill.texture.clamp, true);
+ }
+ if (glop.fill.texture.filter != GL_INVALID_ENUM) {
+ glop.fill.texture.texture->setFilter(glop.fill.texture.filter, true);
+ }
+
+ mCaches->textureState().bindTexture(fill.texture.texture->id);
+ meshState().enableTexCoordsVertexArray();
+ meshState().bindTexCoordsVertexPointer(force, mesh.texCoordOffset, mesh.stride);
} else {
meshState().disableTexCoordsVertexArray();
}
if (mesh.vertexFlags & kColor_Attrib) {
LOG_ALWAYS_FATAL("color vertex attribute not yet supported");
- // TODO: enable color, disable when done
+ // TODO: enable color attribute, disable when done
}
int alphaSlot = -1;
if (mesh.vertexFlags & kAlpha_Attrib) {
const void* alphaCoords = ((const GLbyte*) glop.mesh.vertices) + kVertexAlphaOffset;
- alphaSlot = shader.program->getAttrib("vtxAlpha");
+ alphaSlot = fill.program->getAttrib("vtxAlpha");
glEnableVertexAttribArray(alphaSlot);
glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
}
+ // Shader uniforms
+ SkiaShader::apply(*mCaches, glop.fill.skiaShaderData);
+
// ------------------------------------
// ---------- GL state setup ----------
// ------------------------------------
@@ -275,21 +307,26 @@
if (mesh.indexBufferObject == meshState().getQuadListIBO()) {
// Since the indexed quad list is of limited length, we loop over
// the glDrawXXX method while updating the vertex pointer
- GLsizei elementsCount = mesh.vertexCount;
+ GLsizei elementsCount = mesh.elementCount;
const GLbyte* vertices = static_cast<const GLbyte*>(mesh.vertices);
while (elementsCount > 0) {
GLsizei drawCount = MathUtils::min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
- // TODO: this double binds on first pass
- meshState().bindPositionVertexPointer(true, vertices, mesh.stride);
+ // rebind pointers without forcing, since initial bind handled above
+ meshState().bindPositionVertexPointer(false, vertices, mesh.stride);
+ if (mesh.vertexFlags & kTextureCoord_Attrib) {
+ meshState().bindTexCoordsVertexPointer(false,
+ vertices + kMeshTextureOffset, mesh.stride);
+ }
+
glDrawElements(mesh.primitiveMode, drawCount, GL_UNSIGNED_SHORT, nullptr);
elementsCount -= drawCount;
vertices += (drawCount / 6) * 4 * mesh.stride;
}
} else if (mesh.indexBufferObject || mesh.indices) {
- glDrawElements(mesh.primitiveMode, mesh.vertexCount, GL_UNSIGNED_SHORT, mesh.indices);
+ glDrawElements(mesh.primitiveMode, mesh.elementCount, GL_UNSIGNED_SHORT, mesh.indices);
} else {
- glDrawArrays(mesh.primitiveMode, 0, mesh.vertexCount);
+ glDrawArrays(mesh.primitiveMode, 0, mesh.elementCount);
}
// -----------------------------------
diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp
index 1a638d2..a211de7 100644
--- a/libs/hwui/renderstate/TextureState.cpp
+++ b/libs/hwui/renderstate/TextureState.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <renderstate/TextureState.h>
+#include "renderstate/TextureState.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 6346479..fcf6eb2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -48,7 +48,8 @@
, mCanvas(nullptr)
, mHaveNewSurface(false)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mRootRenderNode(rootRenderNode) {
+ , mRootRenderNode(rootRenderNode)
+ , mCurrentFrameInfo(nullptr) {
mRenderThread.renderState().registerCanvasContext(this);
}
@@ -151,9 +152,13 @@
}
}
-void CanvasContext::prepareTree(TreeInfo& info) {
+void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
mRenderThread.removeFrameCallback(this);
+ mCurrentFrameInfo = &mFrames.next();
+ mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
+ mCurrentFrameInfo->markSyncStart();
+
info.damageAccumulator = &mDamageAccumulator;
info.renderer = mCanvas;
if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
@@ -203,6 +208,7 @@
"drawRenderNode called on a context with no canvas or surface!");
profiler().markPlaybackStart();
+ mCurrentFrameInfo->markIssueDrawCommandsStart();
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -239,12 +245,19 @@
profiler().markPlaybackEnd();
+ // Even if we decided to cancel the frame, from the perspective of jank
+ // metrics the frame was swapped at this point
+ mCurrentFrameInfo->markSwapBuffers();
+
if (drew) {
swapBuffers();
} else {
mEglManager.cancelFrame();
}
+ // TODO: Use a fence for real completion?
+ mCurrentFrameInfo->markFrameCompleted();
+ mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
profiler().finishFrame();
}
@@ -257,9 +270,14 @@
ATRACE_CALL();
profiler().startFrame();
+ int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
+ UiFrameInfoBuilder(frameInfo)
+ .addFlag(FrameInfoFlags::kRTAnimation)
+ .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
+ mRenderThread.timeLord().latestVsync());
TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
- prepareTree(info);
+ prepareTree(info, frameInfo);
if (info.out.canDrawThisFrame) {
draw();
}
@@ -372,6 +390,28 @@
thread.eglManager().setTextureAtlas(buffer, map, mapSize);
}
+void CanvasContext::dumpFrames(int fd) {
+ FILE* file = fdopen(fd, "a");
+ fprintf(file, "\n\n---PROFILEDATA---");
+ for (size_t i = 0; i < mFrames.size(); i++) {
+ FrameInfo& frame = mFrames[i];
+ if (frame[FrameInfoIndex::kSyncStart] == 0) {
+ continue;
+ }
+ fprintf(file, "\n");
+ for (int i = 0; i < static_cast<int>(FrameInfoIndex::kNumIndexes); i++) {
+ fprintf(file, "%" PRId64 ",", frame[i]);
+ }
+ }
+ fprintf(file, "\n---PROFILEDATA---\n\n");
+ fflush(file);
+}
+
+void CanvasContext::resetFrameStats() {
+ mFrames.clear();
+ mRenderThread.jankTracker().reset();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d3fbde8..9a60dc7 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,7 +17,14 @@
#ifndef CANVASCONTEXT_H_
#define CANVASCONTEXT_H_
-#include <set>
+#include "DamageAccumulator.h"
+#include "DrawProfiler.h"
+#include "IContextFactory.h"
+#include "FrameInfo.h"
+#include "RenderNode.h"
+#include "utils/RingBuffer.h"
+#include "renderthread/RenderTask.h"
+#include "renderthread/RenderThread.h"
#include <cutils/compiler.h>
#include <EGL/egl.h>
@@ -25,14 +32,7 @@
#include <utils/Functor.h>
#include <utils/Vector.h>
-#include "../DamageAccumulator.h"
-#include "../DrawProfiler.h"
-#include "../IContextFactory.h"
-#include "../RenderNode.h"
-#include "RenderTask.h"
-#include "RenderThread.h"
-
-#define FUNCTOR_PROCESS_DELAY 4
+#include <set>
namespace android {
namespace uirenderer {
@@ -75,7 +75,7 @@
void setOpaque(bool opaque);
void makeCurrent();
void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
- void prepareTree(TreeInfo& info);
+ void prepareTree(TreeInfo& info, int64_t* uiFrameInfo);
void draw();
void destroy();
@@ -103,6 +103,9 @@
DrawProfiler& profiler() { return mProfiler; }
+ void dumpFrames(int fd);
+ void resetFrameStats();
+
private:
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
@@ -133,6 +136,9 @@
const sp<RenderNode> mRootRenderNode;
DrawProfiler mProfiler;
+ FrameInfo* mCurrentFrameInfo;
+ // Ring buffer large enough for 1 second worth of frames
+ RingBuffer<FrameInfo, 60> mFrames;
std::set<RenderNode*> mPrefetechedLayers;
};
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 4d8a469..f48ee41 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -34,8 +34,6 @@
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
- , mFrameTimeNanos(0)
- , mRecordDurationNanos(0)
, mDensity(1.0f) // safe enough default
, mSyncResult(kSync_OK) {
}
@@ -68,18 +66,12 @@
}
}
-int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
+int DrawFrameTask::drawFrame() {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = kSync_OK;
- mFrameTimeNanos = frameTimeNanos;
- mRecordDurationNanos = recordDurationNanos;
postAndWait();
- // Reset the single-frame data
- mFrameTimeNanos = 0;
- mRecordDurationNanos = 0;
-
return mSyncResult;
}
@@ -93,7 +85,7 @@
ATRACE_NAME("DrawFrame");
mContext->profiler().setDensity(mDensity);
- mContext->profiler().startFrame(mRecordDurationNanos);
+ mContext->profiler().startFrame();
bool canUnblockUiThread;
bool canDrawThisFrame;
@@ -122,7 +114,8 @@
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
- mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
+ int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::kVsync)];
+ mRenderThread->timeLord().vsyncReceived(vsync);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
@@ -130,7 +123,7 @@
mContext->processLayerUpdate(mLayers[i].get());
}
mLayers.clear();
- mContext->prepareTree(info);
+ mContext->prepareTree(info, mFrameInfo);
// This is after the prepareTree so that any pending operations
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 953f012..0e56bea 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -25,6 +25,7 @@
#include "RenderTask.h"
#include "../Rect.h"
+#include "../FrameInfo.h"
#include "../TreeInfo.h"
namespace android {
@@ -62,7 +63,9 @@
void removeLayerUpdate(DeferredLayerUpdater* layer);
void setDensity(float density) { mDensity = density; }
- int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
+ int drawFrame();
+
+ int64_t* frameInfo() { return mFrameInfo; }
virtual void run() override;
@@ -80,12 +83,12 @@
/*********************************************
* Single frame data
*********************************************/
- nsecs_t mFrameTimeNanos;
- nsecs_t mRecordDurationNanos;
float mDensity;
std::vector< sp<DeferredLayerUpdater> > mLayers;
int mSyncResult;
+
+ int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4dc4248..0fa2f23 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,14 +16,14 @@
#include "RenderProxy.h"
-#include "CanvasContext.h"
-#include "RenderTask.h"
-#include "RenderThread.h"
-
-#include "../DeferredLayerUpdater.h"
-#include "../DisplayList.h"
-#include "../LayerRenderer.h"
-#include "../Rect.h"
+#include "DeferredLayerUpdater.h"
+#include "DisplayList.h"
+#include "LayerRenderer.h"
+#include "Rect.h"
+#include "renderthread/CanvasContext.h"
+#include "renderthread/RenderTask.h"
+#include "renderthread/RenderThread.h"
+#include "utils/Macros.h"
namespace android {
namespace uirenderer {
@@ -52,6 +52,12 @@
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
+enum class DumpFlags {
+ kFrameStats = 1 << 0,
+ kReset = 1 << 1,
+};
+MAKE_FLAGS_ENUM(DumpFlags)
+
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
return new CanvasContext(*args->thread, args->translucent,
@@ -92,7 +98,7 @@
}
CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
- args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
+ args->thread->setFrameInterval(args->frameIntervalNanos);
return nullptr;
}
@@ -175,7 +181,8 @@
}
void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density) {
+ mDrawFrameTask.setDensity(density);
SETUP_TASK(setup);
args->context = mContext;
args->width = width;
@@ -199,10 +206,12 @@
post(task);
}
-int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density) {
- mDrawFrameTask.setDensity(density);
- return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
+int64_t* RenderProxy::frameInfo() {
+ return mDrawFrameTask.frameInfo();
+}
+
+int RenderProxy::syncAndDrawFrame() {
+ return mDrawFrameTask.drawFrame();
}
CREATE_BRIDGE1(destroy, CanvasContext* context) {
@@ -375,19 +384,28 @@
mRenderThread.queueAtFront(task);
}
-CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) {
+CREATE_BRIDGE3(dumpProfileInfo, CanvasContext* context, int fd, int dumpFlags) {
args->context->profiler().dumpData(args->fd);
+ if (args->dumpFlags & DumpFlags::kFrameStats) {
+ args->context->dumpFrames(args->fd);
+ }
+ if (args->dumpFlags & DumpFlags::kReset) {
+ args->context->resetFrameStats();
+ }
return nullptr;
}
-void RenderProxy::dumpProfileInfo(int fd) {
+void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
SETUP_TASK(dumpProfileInfo);
args->context = mContext;
args->fd = fd;
+ args->dumpFlags = dumpFlags;
postAndWait(task);
}
-CREATE_BRIDGE1(dumpGraphicsMemory, int fd) {
+CREATE_BRIDGE2(dumpGraphicsMemory, int fd, RenderThread* thread) {
+ args->thread->jankTracker().dump(args->fd);
+
FILE *file = fdopen(args->fd, "a");
if (Caches::hasInstance()) {
String8 cachesLog;
@@ -403,6 +421,7 @@
void RenderProxy::dumpGraphicsMemory(int fd) {
SETUP_TASK(dumpGraphicsMemory);
args->fd = fd;
+ args->thread = &RenderThread::getInstance();
staticPostAndWait(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d87e777..19e73e5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,10 +71,10 @@
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
- uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density);
ANDROID_API void setOpaque(bool opaque);
- ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
- float density);
+ ANDROID_API int64_t* frameInfo();
+ ANDROID_API int syncAndDrawFrame();
ANDROID_API void destroy();
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
@@ -95,7 +95,7 @@
ANDROID_API void stopDrawing();
ANDROID_API void notifyFramePending();
- ANDROID_API void dumpProfileInfo(int fd);
+ ANDROID_API void dumpProfileInfo(int fd, int dumpFlags);
ANDROID_API static void dumpGraphicsMemory(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 9a0fbad..2a8baa7 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -151,6 +151,11 @@
LOG_ALWAYS_FATAL("Can't destroy the render thread");
}
+void RenderThread::setFrameInterval(nsecs_t frameInterval) {
+ mTimeLord.setFrameInterval(frameInterval);
+ mJankTracker->setFrameInterval(frameInterval);
+}
+
void RenderThread::initializeDisplayEventReceiver() {
LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
mDisplayEventReceiver = new DisplayEventReceiver();
@@ -167,6 +172,7 @@
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
mRenderState = new RenderState(*this);
+ mJankTracker = new JankTracker(mTimeLord.frameIntervalNanos());
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 8fc8ca5..f169424 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
#include "RenderTask.h"
-#include <memory>
-#include <set>
+#include "../JankTracker.h"
+#include "TimeLord.h"
#include <cutils/compiler.h>
#include <utils/Looper.h>
@@ -28,7 +28,8 @@
#include <utils/Singleton.h>
#include <utils/Thread.h>
-#include "TimeLord.h"
+#include <memory>
+#include <set>
namespace android {
@@ -85,9 +86,12 @@
// the next vsync. If it is not currently registered this does nothing.
void pushBackFrameCallback(IFrameCallback* callback);
+ void setFrameInterval(nsecs_t frameInterval);
+
TimeLord& timeLord() { return mTimeLord; }
RenderState& renderState() { return *mRenderState; }
EglManager& eglManager() { return *mEglManager; }
+ JankTracker& jankTracker() { return *mJankTracker; }
protected:
virtual bool threadLoop() override;
@@ -132,6 +136,8 @@
TimeLord mTimeLord;
RenderState* mRenderState;
EglManager* mEglManager;
+
+ JankTracker* mJankTracker = nullptr;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f187493..f846d6a 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -32,7 +32,7 @@
return false;
}
-nsecs_t TimeLord::computeFrameTimeMs() {
+nsecs_t TimeLord::computeFrameTimeNanos() {
// Logic copied from Choreographer.java
nsecs_t now = systemTime(CLOCK_MONOTONIC);
nsecs_t jitterNanos = now - mFrameTimeNanos;
@@ -40,7 +40,11 @@
nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
mFrameTimeNanos = now - lastFrameOffset;
}
- return nanoseconds_to_milliseconds(mFrameTimeNanos);
+ return mFrameTimeNanos;
+}
+
+nsecs_t TimeLord::computeFrameTimeMs() {
+ return nanoseconds_to_milliseconds(computeFrameTimeNanos());
}
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 7c155d2..5464399 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -29,9 +29,13 @@
class TimeLord {
public:
void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
+ nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
+
// returns true if the vsync is newer, false if it was rejected for staleness
bool vsyncReceived(nsecs_t vsync);
+ nsecs_t latestVsync() { return mFrameTimeNanos; }
nsecs_t computeFrameTimeMs();
+ nsecs_t computeFrameTimeNanos();
private:
friend class RenderThread;
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index b6d2c4d..b61d72f 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -85,12 +85,10 @@
proxy->initialize(surface);
float lightX = width / 2.0;
proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
- dp(800.0f), 255 * 0.075, 255 * 0.15);
+ dp(800.0f), 255 * 0.075, 255 * 0.15, gDisplay.density);
android::uirenderer::Rect DUMMY;
- std::vector< sp<RenderNode> > cards;
-
DisplayListRenderer* renderer = startRecording(rootNode);
animation.createContent(width, height, renderer);
endRecording(renderer, rootNode);
@@ -100,8 +98,7 @@
ATRACE_NAME("UI-Draw Frame");
animation.doFrame(i);
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
+ proxy->syncAndDrawFrame();
}
sleep(5);
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index fe43fdb..49d364e7 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -16,6 +16,8 @@
#ifndef MACROS_H
#define MACROS_H
+#include <type_traits>
+
#define PREVENT_COPY_AND_ASSIGN(Type) \
private: \
Type(const Type&) = delete; \
@@ -29,4 +31,16 @@
friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \
friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
+#define REQUIRE_COMPATIBLE_LAYOUT(Type) \
+ static_assert(std::is_standard_layout<Type>::value, \
+ #Type " must have standard layout")
+
+#define MAKE_FLAGS_ENUM(enumType) \
+ inline int operator|(enumType lhs, enumType rhs) { \
+ return static_cast<int>(lhs) | static_cast<int>(rhs); \
+ } \
+ inline int operator&(int lhs, enumType rhs) { \
+ return lhs & static_cast<int>(rhs); \
+ }
+
#endif /* MACROS_H */
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 679e2bf..1a5cbf8 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -37,6 +37,13 @@
return resultMode;
}
+ static inline GLenum getFilter(const SkPaint* paint) {
+ if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
+ return GL_LINEAR;
+ }
+ return GL_NEAREST;
+ }
+
// TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
static inline bool paintWillNotDraw(const SkPaint& paint) {
return paint.getAlpha() == 0
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
new file mode 100644
index 0000000..fc9aec0
--- /dev/null
+++ b/libs/hwui/utils/RingBuffer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef RINGBUFFER_H_
+#define RINGBUFFER_H_
+
+#include "utils/Macros.h"
+
+#include <stddef.h>
+
+namespace android {
+namespace uirenderer {
+
+template<class T, size_t SIZE>
+class RingBuffer {
+ PREVENT_COPY_AND_ASSIGN(RingBuffer);
+
+public:
+ RingBuffer() {}
+ ~RingBuffer() {}
+
+ size_t capacity() { return SIZE; }
+ size_t size() { return mCount; }
+
+ T& next() {
+ mHead = (mHead + 1) % SIZE;
+ if (mCount < SIZE) {
+ mCount++;
+ }
+ return mBuffer[mHead];
+ }
+
+ T& front() {
+ return this[0];
+ }
+
+ T& back() {
+ return this[size() - 1];
+ }
+
+ T& operator[](size_t index) {
+ return mBuffer[(mHead + index + 1) % mCount];
+ }
+
+ void clear() {
+ mCount = 0;
+ mHead = -1;
+ }
+
+private:
+ T mBuffer[SIZE];
+ int mHead = -1;
+ size_t mCount = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif /* RINGBUFFER_H_ */
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index ca242e4..97919a9 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -209,8 +209,23 @@
@SystemApi
public final static int FLAG_HW_HOTWORD = 0x1 << 5;
+ /**
+ * @hide
+ * Flag requesting audible playback even under limited interruptions.
+ */
+ @SystemApi
+ public final static int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1 << 6;
+
+ /**
+ * @hide
+ * Flag requesting audible playback even when the underlying stream is muted.
+ */
+ @SystemApi
+ public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
+
private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
- FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD;
+ FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
+ FLAG_BYPASS_MUTE;
private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC;
private int mUsage = USAGE_UNKNOWN;
diff --git a/media/java/android/media/AudioDevicesManager.java b/media/java/android/media/AudioDevicesManager.java
new file mode 100644
index 0000000..bce2100
--- /dev/null
+++ b/media/java/android/media/AudioDevicesManager.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.content.Context;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import android.content.Context;
+
+/** @hide
+ * API candidate
+ */
+public class AudioDevicesManager {
+ private static String TAG = "AudioDevicesManager";
+ private static boolean DEBUG = true;
+
+ private AudioManager mAudioManager = null;
+ private OnAmPortUpdateListener mPortListener = null;
+
+ /*
+ * Enum/Selection API
+ */
+ public AudioDevicesManager(Context context) {
+ mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+ mPortListener = new OnAmPortUpdateListener();
+ mAudioManager.registerAudioPortUpdateListener(mPortListener);
+ }
+
+ /** @hide
+ * API candidate
+ */
+ //TODO Merge this class into android.media.AudioDevice
+ public class AudioDeviceInfo {
+ private AudioDevicePort mPort = null;
+
+ /** @hide */
+ /* package */ AudioDeviceInfo(AudioDevicePort port) {
+ mPort = port;
+ }
+
+ public int getId() { return mPort.handle().id(); }
+
+ public String getName() { return mPort.name(); }
+
+ public int getType() {
+ return mPort.type();
+ }
+
+ public String getAddress() {
+ return mPort.address();
+ }
+
+ public int getRole() { return mPort.role(); }
+
+ public int[] getSampleRates() { return mPort.samplingRates(); }
+
+ public int[] getChannelMasks() { return mPort.channelMasks(); }
+
+ public int[] getChannelCounts() {
+ int[] masks = getChannelMasks();
+ int[] counts = new int[masks.length];
+ for (int mask_index = 0; mask_index < masks.length; mask_index++) {
+ counts[mask_index] = getRole() == AudioPort.ROLE_SINK
+ ? AudioFormat.channelCountFromOutChannelMask(masks[mask_index])
+ : AudioFormat.channelCountFromInChannelMask(masks[mask_index]);
+ }
+ return counts;
+ }
+
+ /* The format IDs are in AudioFormat.java */
+ public int[] getFormats() { return mPort.formats(); }
+
+ public String toString() { return "" + getId() + " - " + getName(); }
+ }
+
+ /** @hide */
+ public static final int LIST_DEVICES_OUTPUTS = 0x0001;
+ /** @hide */
+ public static final int LIST_DEVICES_INPUTS = 0x0002;
+ /** @hide */
+ public static final int LIST_DEVICES_BUILTIN = 0x0004;
+ /** @hide */
+ public static final int LIST_DEVICES_USB = 0x0008;
+ // TODO implement the semantics for these.
+ /** @hide */
+ public static final int LIST_DEVICES_WIRED = 0x0010;
+ /** @hide */
+ public static final int LIST_DEVICES_UNWIRED = 0x0020;
+
+ /** @hide */
+ public static final int LIST_DEVICES_ALL = LIST_DEVICES_OUTPUTS | LIST_DEVICES_INPUTS;
+
+ private boolean checkFlags(AudioDevicePort port, int flags) {
+ // Inputs / Outputs
+ boolean passed =
+ port.role() == AudioPort.ROLE_SINK && (flags & LIST_DEVICES_OUTPUTS) != 0 ||
+ port.role() == AudioPort.ROLE_SOURCE && (flags & LIST_DEVICES_INPUTS) != 0;
+
+ // USB
+ if (passed && (flags & LIST_DEVICES_USB) != 0) {
+ int role = port.role();
+ int type = port.type();
+ Slog.i(TAG, " role:" + role + " type:0x" + Integer.toHexString(type));
+ passed =
+ (role == AudioPort.ROLE_SINK && (type & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
+ (role == AudioPort.ROLE_SOURCE && (type & AudioSystem.DEVICE_IN_ALL_USB) != 0);
+ }
+
+ return passed;
+ }
+
+ /** @hide */
+ public ArrayList<AudioDeviceInfo> listDevices(int flags) {
+ Slog.i(TAG, "AudioManager.listDevices(" + Integer.toHexString(flags) + ")");
+
+ ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>();
+ int status = mAudioManager.listAudioDevicePorts(ports);
+
+ Slog.i(TAG, " status:" + status + " numPorts:" + ports.size());
+
+ ArrayList<AudioDeviceInfo> deviceList = new ArrayList<AudioDeviceInfo>();
+
+ if (status == AudioManager.SUCCESS) {
+ deviceList = new ArrayList<AudioDeviceInfo>();
+ for (AudioDevicePort port : ports) {
+ if (checkFlags(port, flags)) {
+ deviceList.add(new AudioDeviceInfo(port));
+ }
+ }
+ }
+ return deviceList;
+ }
+
+ private ArrayList<OnAudioDeviceConnectionListener> mDeviceConnectionListeners =
+ new ArrayList<OnAudioDeviceConnectionListener>();
+
+ private HashMap<Integer, AudioPort> mCurrentPortlist =
+ new HashMap<Integer, AudioPort>();
+
+ private ArrayList<AudioDeviceInfo> calcAddedDevices(AudioPort[] portList) {
+ ArrayList<AudioDeviceInfo> addedDevices = new ArrayList<AudioDeviceInfo>();
+ synchronized(mCurrentPortlist) {
+ for(int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex] instanceof AudioDevicePort) {
+ if (!mCurrentPortlist.containsKey(portList[portIndex].handle().id())) {
+ addedDevices.add(new AudioDeviceInfo((AudioDevicePort)portList[portIndex]));
+ }
+ }
+ }
+ }
+ return addedDevices;
+ }
+
+ private boolean hasPortId(AudioPort[] portList, int id) {
+ for(int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex].handle().id() == id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ArrayList<AudioDeviceInfo> calcRemovedDevices(AudioPort[] portList) {
+ ArrayList<AudioDeviceInfo> removedDevices = new ArrayList<AudioDeviceInfo>();
+
+ synchronized (mCurrentPortlist) {
+ Iterator it = mCurrentPortlist.entrySet().iterator();
+ while (it.hasNext()) {
+ HashMap.Entry pairs = (HashMap.Entry)it.next();
+ if (pairs.getValue() instanceof AudioDevicePort) {
+ if (!hasPortId(portList, ((Integer)pairs.getKey()).intValue())) {
+ removedDevices.add(new AudioDeviceInfo((AudioDevicePort)pairs.getValue()));
+ }
+ }
+ }
+ }
+ return removedDevices;
+ }
+
+ private void buildCurrentDevicesList(AudioPort[] portList) {
+ synchronized (mCurrentPortlist) {
+ mCurrentPortlist.clear();
+ for (int portIndex = 0; portIndex < portList.length; portIndex++) {
+ if (portList[portIndex] instanceof AudioDevicePort) {
+ mCurrentPortlist.put(portList[portIndex].handle().id(),
+ (AudioDevicePort)portList[portIndex]);
+ }
+ }
+ }
+ }
+
+ /** @hide */
+ public void addDeviceConnectionListener(OnAudioDeviceConnectionListener listener) {
+ synchronized (mDeviceConnectionListeners) {
+ mDeviceConnectionListeners.add(listener);
+ }
+ }
+
+ /** @hide */
+ public void removeDeviceConnectionListener(OnAudioDeviceConnectionListener listener) {
+ synchronized (mDeviceConnectionListeners) {
+ mDeviceConnectionListeners.remove(listener);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener {
+ static final String TAG = "OnAmPortUpdateListener";
+ public void onAudioPortListUpdate(AudioPort[] portList) {
+ Slog.i(TAG, "onAudioPortListUpdate() " + portList.length + " ports.");
+ ArrayList<AudioDeviceInfo> addedDevices = calcAddedDevices(portList);
+ ArrayList<AudioDeviceInfo> removedDevices = calcRemovedDevices(portList);
+
+ ArrayList<OnAudioDeviceConnectionListener> listeners = null;
+ synchronized (mDeviceConnectionListeners) {
+ listeners =
+ new ArrayList<OnAudioDeviceConnectionListener>(mDeviceConnectionListeners);
+ }
+
+ // Connect
+ if (addedDevices.size() != 0) {
+ for (OnAudioDeviceConnectionListener listener : listeners) {
+ listener.onConnect(addedDevices);
+ }
+ }
+
+ // Disconnect?
+ if (removedDevices.size() != 0) {
+ for (OnAudioDeviceConnectionListener listener : listeners) {
+ listener.onDisconnect(removedDevices);
+ }
+ }
+
+ buildCurrentDevicesList(portList);
+ }
+
+ /**
+ * Callback method called upon audio patch list update.
+ * @param patchList the updated list of audio patches
+ */
+ public void onAudioPatchListUpdate(AudioPatch[] patchList) {
+ Slog.i(TAG, "onAudioPatchListUpdate() " + patchList.length + " patches.");
+ }
+
+ /**
+ * Callback method called when the mediaserver dies
+ */
+ public void onServiceDied() {
+ Slog.i(TAG, "onServiceDied()");
+ }
+ }
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7084eba..9876995 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3334,6 +3334,19 @@
* Only useful for volume controllers.
* @hide
*/
+ public boolean isStreamAffectedByMute(int streamType) {
+ try {
+ return getService().isStreamAffectedByMute(streamType);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling isStreamAffectedByMute", e);
+ return false;
+ }
+ }
+
+ /**
+ * Only useful for volume controllers.
+ * @hide
+ */
public void disableSafeMediaVolume() {
try {
getService().disableSafeMediaVolume();
@@ -3446,14 +3459,14 @@
* @see listAudioPorts(ArrayList<AudioPort>)
* @hide
*/
- public int listAudioDevicePorts(ArrayList<AudioPort> devices) {
+ public int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
int status = updateAudioPortCache(ports, null);
if (status == SUCCESS) {
devices.clear();
for (int i = 0; i < ports.size(); i++) {
if (ports.get(i) instanceof AudioDevicePort) {
- devices.add(ports.get(i));
+ devices.add((AudioDevicePort)ports.get(i));
}
}
}
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index 873c142..ef5710c 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -15,8 +15,6 @@
*/
package android.media;
-import android.os.IBinder;
-
import com.android.server.LocalServices;
/**
@@ -47,6 +45,8 @@
public abstract void setRingerModeInternal(int ringerMode, String caller);
+ public abstract int getVolumeControllerUid();
+
public interface RingerModeDelegate {
/** Called when external ringer mode is evaluated, returns the new internal ringer mode */
int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index caccb6e..cd78234 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1178,6 +1178,9 @@
}
private boolean isRestricted() {
+ if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
+ return false;
+ }
try {
final int usage = AudioAttributes.usageForLegacyStreamType(mStreamType);
final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, usage,
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index dabd9c2..17f5b59 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -202,6 +202,8 @@
boolean isStreamAffectedByRingerMode(int streamType);
+ boolean isStreamAffectedByMute(int streamType);
+
void disableSafeMediaVolume();
int setHdmiSystemAudioSupported(boolean on);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 615dac2..fc372eb 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -604,6 +604,7 @@
private final IAppOpsService mAppOps;
private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
private int mUsage = -1;
+ private boolean mBypassInterruptionPolicy;
/**
* Default constructor. Consider using one of the create() methods for
@@ -1169,6 +1170,9 @@
private native void _start() throws IllegalStateException;
private boolean isRestricted() {
+ if (mBypassInterruptionPolicy) {
+ return false;
+ }
try {
final int usage = mUsage != -1 ? mUsage
: AudioAttributes.usageForLegacyStreamType(getAudioStreamType());
@@ -1560,6 +1564,8 @@
throw new IllegalArgumentException(msg);
}
mUsage = attributes.getUsage();
+ mBypassInterruptionPolicy = (attributes.getFlags()
+ & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0;
Parcel pattributes = Parcel.obtain();
attributes.writeToParcel(pattributes, AudioAttributes.FLATTEN_TAGS);
setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, pattributes);
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 81d5afe..97b3f63 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -437,10 +437,7 @@
public void setCaptureRate(double fps) {
// Make sure that time lapse is enabled when this method is called.
setParameter("time-lapse-enable=1");
-
- double timeBetweenFrameCapture = 1 / fps;
- long timeBetweenFrameCaptureUs = (long) (1000000 * timeBetweenFrameCapture);
- setParameter("time-between-time-lapse-frame-capture=" + timeBetweenFrameCaptureUs);
+ setParameter("time-lapse-fps=" + fps);
}
/**
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 5285074..b4c612a 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -17,6 +17,7 @@
package android.media;
import android.Manifest;
+import android.annotation.DrawableRes;
import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -2083,7 +2084,7 @@
*
* @param resId Resource ID of an icon drawable to use to represent this route
*/
- public void setIconResource(int resId) {
+ public void setIconResource(@DrawableRes int resId) {
setIconDrawable(sStatic.mResources.getDrawable(resId));
}
@@ -2393,7 +2394,7 @@
*
* @param resId Resource ID of an icon drawable to use to represent this group
*/
- public void setIconResource(int resId) {
+ public void setIconResource(@DrawableRes int resId) {
setIconDrawable(sStatic.mResources.getDrawable(resId));
}
diff --git a/core/java/android/midi/IMidiDeviceServer.aidl b/media/java/android/media/OnAudioDeviceConnectionListener.java
similarity index 60%
copy from core/java/android/midi/IMidiDeviceServer.aidl
copy to media/java/android/media/OnAudioDeviceConnectionListener.java
index 31fdbbb..4bdd4d0 100644
--- a/core/java/android/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/OnAudioDeviceConnectionListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-package android.midi;
+package android.media;
-import android.os.ParcelFileDescriptor;
+import java.util.ArrayList;
-/** @hide */
-interface IMidiDeviceServer
-{
- ParcelFileDescriptor openInputPort(int portNumber);
- ParcelFileDescriptor openOutputPort(int portNumber);
+/**
+ * @hide
+ * API candidate
+ */
+public abstract class OnAudioDeviceConnectionListener {
+ public void onConnect(ArrayList<AudioDevicesManager.AudioDeviceInfo> devices) {}
+ public void onDisconnect(ArrayList<AudioDevicesManager.AudioDeviceInfo> devices) {}
}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 32d5b82..db6b38b 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -608,6 +608,9 @@
int priority, int loop, float rate);
private boolean isRestricted() {
+ if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
+ return false;
+ }
try {
final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO,
mAttributes.getUsage(),
diff --git a/core/java/android/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
similarity index 96%
rename from core/java/android/midi/IMidiDeviceServer.aidl
rename to media/java/android/media/midi/IMidiDeviceServer.aidl
index 31fdbbb..71914ad 100644
--- a/core/java/android/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.ParcelFileDescriptor;
diff --git a/core/java/android/midi/IMidiListener.aidl b/media/java/android/media/midi/IMidiListener.aidl
similarity index 91%
rename from core/java/android/midi/IMidiListener.aidl
rename to media/java/android/media/midi/IMidiListener.aidl
index b650593..a4129e9 100644
--- a/core/java/android/midi/IMidiListener.aidl
+++ b/media/java/android/media/midi/IMidiListener.aidl
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
-import android.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceInfo;
/** @hide */
oneway interface IMidiListener
diff --git a/core/java/android/midi/IMidiManager.aidl b/media/java/android/media/midi/IMidiManager.aidl
similarity index 89%
rename from core/java/android/midi/IMidiManager.aidl
rename to media/java/android/media/midi/IMidiManager.aidl
index 575b525..bba35f5 100644
--- a/core/java/android/midi/IMidiManager.aidl
+++ b/media/java/android/media/midi/IMidiManager.aidl
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
-import android.midi.IMidiDeviceServer;
-import android.midi.IMidiListener;
-import android.midi.MidiDeviceInfo;
+import android.media.midi.IMidiDeviceServer;
+import android.media.midi.IMidiListener;
+import android.media.midi.MidiDeviceInfo;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/core/java/android/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
similarity index 98%
rename from core/java/android/midi/MidiDevice.java
rename to media/java/android/media/midi/MidiDevice.java
index b91aedf..36710fd 100644
--- a/core/java/android/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
diff --git a/core/java/android/midi/MidiDeviceInfo.aidl b/media/java/android/media/midi/MidiDeviceInfo.aidl
similarity index 95%
rename from core/java/android/midi/MidiDeviceInfo.aidl
rename to media/java/android/media/midi/MidiDeviceInfo.aidl
index 59be059..f2f37a2 100644
--- a/core/java/android/midi/MidiDeviceInfo.aidl
+++ b/media/java/android/media/midi/MidiDeviceInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
parcelable MidiDeviceInfo;
diff --git a/core/java/android/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
similarity index 99%
rename from core/java/android/midi/MidiDeviceInfo.java
rename to media/java/android/media/midi/MidiDeviceInfo.java
index dde2669..fd35052 100644
--- a/core/java/android/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/core/java/android/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
similarity index 97%
rename from core/java/android/midi/MidiDeviceServer.java
rename to media/java/android/media/midi/MidiDeviceServer.java
index 7499934..3317baa 100644
--- a/core/java/android/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -254,12 +254,12 @@
return new MidiReceiver() {
@Override
- public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
+ public void post(byte[] msg, int offset, int count, long timestamp) throws IOException {
ArrayList<MidiInputPort> receivers = mOutputPortReceivers[portNumberF];
synchronized (receivers) {
for (int i = 0; i < receivers.size(); i++) {
// FIXME catch errors and remove dead ones
- receivers.get(i).onPost(msg, offset, count, timestamp);
+ receivers.get(i).post(msg, offset, count, timestamp);
}
}
}
diff --git a/core/java/android/midi/MidiInputPort.java b/media/java/android/media/midi/MidiInputPort.java
similarity index 94%
rename from core/java/android/midi/MidiInputPort.java
rename to media/java/android/media/midi/MidiInputPort.java
index 51c47dd..730d364 100644
--- a/core/java/android/midi/MidiInputPort.java
+++ b/media/java/android/media/midi/MidiInputPort.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.ParcelFileDescriptor;
@@ -50,7 +50,7 @@
* @param timestamp future time to post the message (based on
* {@link java.lang.System#nanoTime}
*/
- public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
+ public void post(byte[] msg, int offset, int count, long timestamp) throws IOException {
assert(offset >= 0 && count >= 0 && offset + count <= msg.length);
synchronized (mBuffer) {
diff --git a/core/java/android/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
similarity index 77%
rename from core/java/android/midi/MidiManager.java
rename to media/java/android/media/midi/MidiManager.java
index 8aa8395..410120d 100644
--- a/core/java/android/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
@@ -50,38 +51,60 @@
// Binder stub for receiving device notifications from MidiService
private class DeviceListener extends IMidiListener.Stub {
- private DeviceCallback mCallback;
+ private final DeviceCallback mCallback;
+ private final Handler mHandler;
- public DeviceListener(DeviceCallback callback) {
+ public DeviceListener(DeviceCallback callback, Handler handler) {
mCallback = callback;
+ mHandler = handler;
}
public void onDeviceAdded(MidiDeviceInfo device) {
- mCallback.onDeviceAdded(device);
+ if (mHandler != null) {
+ final MidiDeviceInfo deviceF = device;
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ mCallback.onDeviceAdded(deviceF);
+ }
+ });
+ } else {
+ mCallback.onDeviceAdded(device);
+ }
}
public void onDeviceRemoved(MidiDeviceInfo device) {
- mCallback.onDeviceRemoved(device);
+ if (mHandler != null) {
+ final MidiDeviceInfo deviceF = device;
+ mHandler.post(new Runnable() {
+ @Override public void run() {
+ mCallback.onDeviceRemoved(deviceF);
+ }
+ });
+ } else {
+ mCallback.onDeviceRemoved(device);
+ }
}
}
/**
- * Callback interface used for clients to receive MIDI device added and removed notifications
+ * Callback class used for clients to receive MIDI device added and removed notifications
*/
- public interface DeviceCallback {
+ public static class DeviceCallback {
/**
* Called to notify when a new MIDI device has been added
*
* @param device a {@link MidiDeviceInfo} for the newly added device
*/
- void onDeviceAdded(MidiDeviceInfo device);
+ public void onDeviceAdded(MidiDeviceInfo device) {
+ }
/**
* Called to notify when a MIDI device has been removed
*
* @param device a {@link MidiDeviceInfo} for the removed device
*/
- void onDeviceRemoved(MidiDeviceInfo device);
+ public void onDeviceRemoved(MidiDeviceInfo device) {
+ }
}
/**
@@ -96,9 +119,12 @@
* Registers a callback to receive notifications when MIDI devices are added and removed.
*
* @param callback a {@link DeviceCallback} for MIDI device notifications
+ * @param handler The {@link android.os.Handler Handler} that will be used for delivering the
+ * device notifications. If handler is null, then the thread used for the
+ * callback is unspecified.
*/
- public void registerDeviceCallback(DeviceCallback callback) {
- DeviceListener deviceListener = new DeviceListener(callback);
+ public void registerDeviceCallback(DeviceCallback callback, Handler handler) {
+ DeviceListener deviceListener = new DeviceListener(callback, handler);
try {
mService.registerListener(mToken, deviceListener);
} catch (RemoteException e) {
@@ -141,7 +167,7 @@
/**
* Opens a MIDI device for reading and writing.
*
- * @param deviceInfo a {@link android.midi.MidiDeviceInfo} to open
+ * @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open
* @return a {@link MidiDevice} object for the device
*/
public MidiDevice openDevice(MidiDeviceInfo deviceInfo) {
diff --git a/core/java/android/midi/MidiOutputPort.java b/media/java/android/media/midi/MidiOutputPort.java
similarity index 97%
rename from core/java/android/midi/MidiOutputPort.java
rename to media/java/android/media/midi/MidiOutputPort.java
index 332b431..83ddeeb 100644
--- a/core/java/android/midi/MidiOutputPort.java
+++ b/media/java/android/media/midi/MidiOutputPort.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -65,7 +65,7 @@
for (int i = 0; i < mReceivers.size(); i++) {
MidiReceiver receiver = mReceivers.get(i);
try {
- receiver.onPost(buffer, offset, size, timestamp);
+ receiver.post(buffer, offset, size, timestamp);
} catch (IOException e) {
Log.e(TAG, "post failed");
deadReceivers.add(receiver);
diff --git a/core/java/android/midi/MidiPort.java b/media/java/android/media/midi/MidiPort.java
similarity index 77%
rename from core/java/android/midi/MidiPort.java
rename to media/java/android/media/midi/MidiPort.java
index 7512a90..4d3c91d 100644
--- a/core/java/android/midi/MidiPort.java
+++ b/media/java/android/media/midi/MidiPort.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import android.util.Log;
@@ -33,12 +33,16 @@
private final int mPortNumber;
/**
- * Maximum size of a packet that can pass through our ParcelFileDescriptor
+ * Maximum size of a packet that can pass through our ParcelFileDescriptor.
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
- protected static final int MAX_PACKET_SIZE = 1024;
+ public static final int MAX_PACKET_SIZE = 1024;
/**
* size of message timestamp in bytes
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
private static final int TIMESTAMP_SIZE = 8;
@@ -65,6 +69,7 @@
* Called when an IOExeption occurs while sending or receiving data.
* Subclasses can override to be notified of such errors
*
+ * @hide
*/
public void onIOException() {
}
@@ -77,8 +82,11 @@
* timestamp is message timestamp to pack
* dest is buffer to pack into
* returns size of packed message
+ *
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
- protected static int packMessage(byte[] message, int offset, int size, long timestamp,
+ public static int packMessage(byte[] message, int offset, int size, long timestamp,
byte[] dest) {
if (size + TIMESTAMP_SIZE > MAX_PACKET_SIZE) {
size = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
@@ -98,8 +106,11 @@
/**
* Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
* returns the offset of the MIDI message in packed buffer
+ *
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
- protected static int getMessageOffset(byte[] buffer, int bufferLength) {
+ public static int getMessageOffset(byte[] buffer, int bufferLength) {
// message is at the beginning
return 0;
}
@@ -107,8 +118,11 @@
/**
* Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
* returns size of MIDI data in packed buffer
+ *
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
- protected static int getMessageSize(byte[] buffer, int bufferLength) {
+ public static int getMessageSize(byte[] buffer, int bufferLength) {
// message length is total buffer length minus size of the timestamp
return bufferLength - TIMESTAMP_SIZE;
}
@@ -116,8 +130,11 @@
/**
* Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
* unpacks timestamp from packed buffer
+ *
+ * For internal use only. Implementation details may change in the future.
+ * @hide
*/
- protected static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
+ public static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
// timestamp is at end of the packet
int offset = bufferLength;
long timestamp = 0;
diff --git a/core/java/android/midi/MidiReceiver.java b/media/java/android/media/midi/MidiReceiver.java
similarity index 87%
rename from core/java/android/midi/MidiReceiver.java
rename to media/java/android/media/midi/MidiReceiver.java
index fdfe51a..64c0c07 100644
--- a/core/java/android/midi/MidiReceiver.java
+++ b/media/java/android/media/midi/MidiReceiver.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
import java.io.IOException;
/**
- * Interface for receiving data from a MIDI device.
+ * Interface for sending and receiving data to and from a MIDI device.
*
* CANDIDATE FOR PUBLIC API
* @hide
@@ -32,7 +32,7 @@
* The msg bytes should be copied by the receiver rather than retaining a reference
* to this parameter.
* Also, modifying the contents of the msg array parameter may result in other receivers
- * in the same application receiving incorrect values in their onPost() method.
+ * in the same application receiving incorrect values in their post() method.
*
* @param msg a byte array containing the MIDI data
* @param offset the offset of the first byte of the data in the byte array
@@ -40,5 +40,5 @@
* @param timestamp the timestamp of the message (based on {@link java.lang.System#nanoTime}
* @throws IOException
*/
- public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException;
+ public void post(byte[] msg, int offset, int count, long timestamp) throws IOException;
}
diff --git a/core/java/android/midi/MidiSender.java b/media/java/android/media/midi/MidiSender.java
similarity index 97%
rename from core/java/android/midi/MidiSender.java
rename to media/java/android/media/midi/MidiSender.java
index 2b7afad..4550476 100644
--- a/core/java/android/midi/MidiSender.java
+++ b/media/java/android/media/midi/MidiSender.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.midi;
+package android.media.midi;
/**
* Interface provided by a device to allow attaching
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 5406130..cf69b8f 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -430,7 +430,7 @@
pData = buffer->data;
dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
break;
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// Single plane 16bpp bayer data.
bytesPerPixel = 2;
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -517,7 +517,7 @@
pixelStride = 0;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
case HAL_PIXEL_FORMAT_RGB_565:
// Single plane 16bpp data.
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
@@ -584,7 +584,7 @@
rowStride = buffer->stride;
break;
case HAL_PIXEL_FORMAT_Y16:
- case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RAW16:
// In native side, strides are specified in pixels, not in bytes.
// Single plane 16bpp bayer data. even width/height,
// row stride multiple of 16 pixels (32 bytes)
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index cabc956..8c490ea 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -20,7 +20,7 @@
<string name="title_open" msgid="4353228937663917801">"Բացել այստեղից"</string>
<string name="title_save" msgid="2433679664882857999">"Պահել այստեղ"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"Ստեղծել թղթապանակ"</string>
- <string name="menu_grid" msgid="6878021334497835259">"Ցանցային տեսք"</string>
+ <string name="menu_grid" msgid="6878021334497835259">"Ցանցի տեսք"</string>
<string name="menu_list" msgid="7279285939892417279">"Ցուցակի տեսք"</string>
<string name="menu_sort" msgid="7677740407158414452">"Դասավորել ըստ"</string>
<string name="menu_search" msgid="3816712084502856974">"Որոնել"</string>
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index cff2fc7..7dcaf6d 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -64,6 +64,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:src="@drawable/ic_lockscreen_ime"
+ android:contentDescription="@string/accessibility_ime_switch_button"
android:clickable="true"
android:padding="8dip"
android:layout_gravity="end|center_vertical"
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index 287d1e4..e4b543b 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou tablet te ontsluit deur middel van \'n e-posrekening.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Verkeerde SIM PIN-kode, jy sal nou jou diensverskaffer moet kontak om jou toestel te ontsluit."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Verkeerde SIM PIN-kode, jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende poging voordat jy jou diensverskaffer sal moet kontak om jou toestel te ontsluit."</item>
- <item quantity="other" msgid="2215723361575359486">"Verkeerde SIM PIN-kode, jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende pogings."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Verkeerde SIM-PIN-kode. Jy het <xliff:g id="NUMBER_1">%d</xliff:g> pogings oor.</item>
+ <item quantity="one">Verkeerde SIM-PIN-kode. Jy het <xliff:g id="NUMBER_0">%d</xliff:g> poging oor voordat jy jou diensverskaffer moet kontak om jou toestel te ontsluit.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM is onbruikbaar. Kontak jou diensverskaffer."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Verkeerde SIM PUK-kode, jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende poging voordat SIM permanent onbruikbaar word."</item>
- <item quantity="other" msgid="5477305226026342036">"Verkeerde SIM PUK-kode, jy het <xliff:g id="NUMBER">%d</xliff:g> oorblywende pogings voordat SIM permanent onbruikbaar word."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Verkeerde SIM-PUK-kode. Jy het <xliff:g id="NUMBER_1">%d</xliff:g> pogings oor voordat SIM permanent onbruikbaar word.</item>
+ <item quantity="one">Verkeerde SIM-PUK-kode. Jy het <xliff:g id="NUMBER_0">%d</xliff:g> poging oor voordat SIM permanent onbruikbaar word.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN-bewerking het misluk!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK-bewerking het misluk!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kode is aanvaar!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen diens nie."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
</resources>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index 3e7e997..c54656e 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ጡባዊ ቱኮዎን እንዲከፍቱ ይጠየቃሉ።\n\n ከ<xliff:g id="NUMBER_2">%d</xliff:g> ከሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ልክ ያልሆነ የሲም ኮድ። አሁን መሳሪያዎን ለማስከፈት ድምጸ ተያያዥ ሞደምዎን ማግኘት አለብዎ።"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ልክ ያልሆነ የሲም ፒን ኮድ፣ መሳሪያዎን ለማስከፈት ድምጸ ተያያዥ ሞደምዎን ማግኘት ግዴታዎ ሊሆን <xliff:g id="NUMBER">%d</xliff:g> ሙከራ ይቀርዎታል።"</item>
- <item quantity="other" msgid="2215723361575359486">"ልክ ያልሆነ የሲም ፒን ኮድ፣ <xliff:g id="NUMBER">%d</xliff:g> ሙከራዎች ይቀሩዎታል።"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <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="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"ሲሙ ጥቅም ላይ መዋል እይችልም። የእርስዎን ድምጸ ተያያዥ ሞደም ያግኙ።"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ልክ ያልሆነ የሲም PUK ኮድ፣ ሲም ካርድዎ በቋሚነት ጥቅም ላይ መዋል የማይችል ሊሆን <xliff:g id="NUMBER">%d</xliff:g> ሙከራ ይቀርዎታል።"</item>
- <item quantity="other" msgid="5477305226026342036">"ልክ ያልሆነ የሲም PUK ኮድ፣ ሲም ካርድዎ በቋሚነት ጥቅም ላይ መዋል የማይችል ሊሆን <xliff:g id="NUMBER">%d</xliff:g> ሙከራዎች ይቀሩዎታል።"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">ልክ ያልሆነ የሲም PUK ኮድ፣ ሲም ካርድዎ በቋሚነት ጥቅም ላይ መዋል የማይችል ሊሆን <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀሩዎታል።</item>
+ <item quantity="other">ልክ ያልሆነ የሲም PUK ኮድ፣ ሲም ካርድዎ በቋሚነት ጥቅም ላይ መዋል የማይችል ሊሆን <xliff:g id="NUMBER_1">%d</xliff:g> ሙከራዎች ይቀሩዎታል።</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"የሲም ፒን ክወና አልተሳካም!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"የሲም PUK ክወና አልተሳካም!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ኮዱ ተቀባይነት አግኝቷል!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ከአገልግሎት መስጫ ክልል ውጪ።"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</string>
</resources>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 408096f..153f08e6 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -34,16 +34,16 @@
<string name="keyguard_low_battery" msgid="8143808018719173859">"توصيل جهاز الشحن."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"اضغط على \"القائمة\" لإلغاء القفل."</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"الشبكة مؤمّنة"</string>
- <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"ليست هناك بطاقة SIM"</string>
- <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"ليست هناك بطاقة SIM في الجهاز اللوحي."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"ليست هناك بطاقة SIM في الهاتف."</string>
- <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"أدخل بطاقة SIM."</string>
- <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"بطاقة SIM مفقودة أو غير قابلة للقراءة. أدخل بطاقة SIM."</string>
- <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"بطاقة SIM غير قابلة للاستخدام."</string>
- <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"تم تعطيل بطاقة SIM بشكل دائم.\n اتصل بمقدم خدمة اللاسلكي للحصول على بطاقة SIM أخرى."</string>
- <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"بطاقة SIM مؤمّنة."</string>
- <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"بطاقة SIM مؤمّنة بكود PUK."</string>
- <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
+ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"ليست هناك شريحة SIM"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"ليست هناك شريحة SIM في الجهاز اللوحي."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"ليست هناك شريحة SIM في الهاتف."</string>
+ <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"أدخل شريحة SIM."</string>
+ <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"شريحة SIM مفقودة أو غير قابلة للقراءة. أدخل شريحة SIM."</string>
+ <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"شريحة SIM غير قابلة للاستخدام."</string>
+ <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"تم تعطيل شريحة SIM بشكل دائم.\n اتصل بمقدم خدمة اللاسلكي للحصول على شريحة SIM أخرى."</string>
+ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"شريحة SIM مؤمّنة."</string>
+ <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"شريحة SIM مؤمّنة بكود PUK."</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"جارٍ إلغاء تأمين شريحة SIM…"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"تأمين الجهاز بالوجه."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رمز PIN."</string>
@@ -67,14 +67,14 @@
<string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"إدخال رقم التعريف الشخصي لبطاقة SIM التابعة للمشغل \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"أدخل رمز PIN"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"أدخل كلمة المرور"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"بطاقة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"شريحة SIM معطلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوال للاطلاع على التفاصيل."</string>
<string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" معطلة الآن. أدخل رمز PUK للمتابعة. واتصل بمشغل شبكة الجوال لمعرفة التفاصيل."</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رمز PIN المراد"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين شريحة SIM…"</string>
<string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK 8 أرقام أو أكثر."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل بطاقة SIM نهائيًا."</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل شريحة SIM نهائيًا."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"لقد كتبت رمز PIN بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
@@ -95,17 +95,26 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستطالَب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات حساب بريد إلكتروني.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"رمز \"رقم التعريف الشخصي\" لبطاقة SIM غير صحيح، ويلزمك الاتصال الآن بمشغّل شبكة الجوّال لإلغاء قفل الجهاز."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"رمز \"رقم التعريف الشخصي\" لبطاقة SIM غير صحيح، ويتبقى لديك محاولة واحدة (<xliff:g id="NUMBER">%d</xliff:g>) يتعين عليك بعدها الاتصال بمشغّل شبكة الجوّال لإلغاء قفل الجهاز."</item>
- <item quantity="other" msgid="2215723361575359486">"رمز \"رقم التعريف الشخصي\" لبطاقة SIM غير صحيح، يتبقى لديك <xliff:g id="NUMBER">%d</xliff:g> من المحاولات."</item>
- </plurals>
- <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"بطاقة SIM غير صالحة للاستخدام. يُرجى الاتصال بمشغّل شبكة الجوّال."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"رمز PUK لبطاقة SIM غير صالح، ويتبقى لديك محاولة واحدة (<xliff:g id="NUMBER">%d</xliff:g>)، تصبح بعدها بطاقة SIM غير صالحة للاستخدام بشكل دائم."</item>
- <item quantity="other" msgid="5477305226026342036">"رمز PUK لبطاقة SIM غير صالح، ويتبقى لديك <xliff:g id="NUMBER">%d</xliff:g> من المحاولات، تصبح بعدها بطاقة SIM غير صالحة للاستخدام بشكل دائم."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="zero">رمز رقم التعريف الشخصي لبطاقة SIM غير صحيح، ولم تتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
+ <item quantity="two">رمز رقم التعريف الشخصي لبطاقة SIM غير صحيح، ويتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>).</item>
+ <item quantity="few">رمز رقم التعريف الشخصي لبطاقة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات.</item>
+ <item quantity="many">رمز رقم التعريف الشخصي لبطاقة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة.</item>
+ <item quantity="other">رمز رقم التعريف الشخصي\" لبطاقة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات.</item>
+ <item quantity="one">رمز رقم التعريف الشخصي لبطاقة SIM غير صحيح، ويتبقى لديك محاولة واحدة (<xliff:g id="NUMBER_0">%d</xliff:g>) يتعين عليك بعدها الاتصال بمشغّل شبكة الجوّال لإلغاء قفل الجهاز.</item>
+ </plurals>
+ <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"شريحة SIM غير صالحة للاستخدام. يُرجى الاتصال بمشغّل شبكة الجوّال."</string>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="zero">رمز PUK لشريحة SIM غير صحيح، ولم تتبق لديك أية محاولات (<xliff:g id="NUMBER_1">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="two">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك محاولتان (<xliff:g id="NUMBER_1">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="few">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولات تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="many">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> محاولة تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="other">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ <item quantity="one">رمز PUK لشريحة SIM غير صحيح، ويتبقى لديك محاولة واحدة (<xliff:g id="NUMBER_0">%d</xliff:g>) تصبح بعدها شريحة SIM غير صالحة للاستخدام بشكل دائم.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"أخفقت عملية \"رقم التعريف الشخصي\" لبطاقة SIM!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"أخفقت عملية PUK لبطاقة SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"تم قبول الرمز!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"لا تتوفر خدمة"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</string>
</resources>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index 6eb8a73..5dcb82c 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Неправилен ПИН код за SIM картата – сега трябва да се свържете с оператора си, за да отключите устройството."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Неправилен ПИН код за SIM картата – остава ви <xliff:g id="NUMBER">%d</xliff:g> опит, преди да трябва да се свържете с оператора си, за да отключите устройството."</item>
- <item quantity="other" msgid="2215723361575359486">"Неправилен ПИН код за SIM картата – остават ви <xliff:g id="NUMBER">%d</xliff:g> опита."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Неправилен ПИН код за SIM картата – остават ви <xliff:g id="NUMBER_1">%d</xliff:g> опита.</item>
+ <item quantity="one">Неправилен ПИН код за SIM картата – остава ви <xliff:g id="NUMBER_0">%d</xliff:g> опит, преди да трябва да се свържете с оператора си, за да отключите устройството.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM картата е неизползваема. Свържете се с оператора си."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Неправилен PUK код за SIM картата – остава ви <xliff:g id="NUMBER">%d</xliff:g> опит, преди SIM картата да стане неизползваема завинаги."</item>
- <item quantity="other" msgid="5477305226026342036">"Неправилен PUK код за SIM картата – остават ви <xliff:g id="NUMBER">%d</xliff:g> опита, преди SIM картата да стане неизползваема завинаги."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Неправилен PUK код за SIM картата – остават ви <xliff:g id="NUMBER_1">%d</xliff:g> опита, преди тя да стане неизползваема завинаги.</item>
+ <item quantity="one">Неправилен PUK код за SIM картата – остава ви <xliff:g id="NUMBER_0">%d</xliff:g> опит, преди тя да стане неизползваема завинаги.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Операцията с ПИН кода за SIM картата не бе успешна!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Операцията с PUK кода за SIM картата не бе успешна!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кодът е приет!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Няма покритие."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Бутон за превключване на метода на въвеждане."</string>
</resources>
diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml
index 35a5531..2b13a07 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ট্যাবলেট আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ভুল সিম PIN কোড, আপনার ডিভাইসটি আনলক করতে এখন আপনাকে অবশ্যই আপনার ক্যারিয়ারের সাথে যোগাযোগ করতে হবে৷"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ভুল সিম PIN কোড, আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে, তার পরে আপনার ডিভাইসটি আনলক করতে আপনাকে অবশ্যই আপনার ক্যারিয়ারের সাথে যোগাযোগ করতে হবে৷"</item>
- <item quantity="other" msgid="2215723361575359486">"ভুল সিম PIN কোড, আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">ভুল SIM PIN কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+ <item quantity="other">ভুল SIM PIN কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে৷</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIMটি ব্যবহারের অযোগ্য৷ আপনার ক্যারিয়ারের সাথে যোগাযোগ করুন৷"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷"</item>
- <item quantity="other" msgid="5477305226026342036">"ভুল সিম PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার সিম স্থায়ীভাবে অব্যবহারযোগ্য হবে৷"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+ <item quantity="other">ভুল SIM PUK কোড, আপনার কাছে আর <xliff:g id="NUMBER_1">%d</xliff:g>টি প্রচেষ্টা বাকি রয়েছে এটির পরেই আপনার SIM স্থায়ীভাবে অব্যবহারযোগ্য হবে৷</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"সিম PIN ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"সিম PUK ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"কোড স্বীকৃত হয়েছে!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"কোনো পরিষেবা নেই৷"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ইনপুট পদ্ধতির বোতাম পরিবর্তন করুন৷"</string>
</resources>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index 1e13d40..e675c7a 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se\'t demanarà que desbloquegis la tauleta amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"El codi PIN de la SIM no és correcte. Has de contactar amb l\'operador de telefonia mòbil per desbloquejar el dispositiu."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"El codi PIN de la SIM no és correcte. Et queda <xliff:g id="NUMBER">%d</xliff:g> intent; si no l\'encertes, contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu."</item>
- <item quantity="other" msgid="2215723361575359486">"El codi PIN de la SIM no és correcte. Et queden <xliff:g id="NUMBER">%d</xliff:g> intents."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">El codi PIN de la SIM no és correcte. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents.</item>
+ <item quantity="one">El codi PIN de la SIM no és correcte. Et queda <xliff:g id="NUMBER_0">%d</xliff:g> intent; si no l\'encertes, contacta amb l\'operador de telefonia mòbil per desbloquejar el dispositiu.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"La SIM no es pot utilitzar. Contacta amb l\'operador de telefonia mòbil."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"El codi PUK de la SIM no és correcte. Et queda <xliff:g id="NUMBER">%d</xliff:g> intent; si no l\'encertes, la SIM no es podrà tornar a fer servir."</item>
- <item quantity="other" msgid="5477305226026342036">"El codi PUK de la SIM no és correcte. Et queden <xliff:g id="NUMBER">%d</xliff:g> intents; si no l\'encertes, la SIM no es podrà tornar a fer servir."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">El codi PUK de la SIM no és correcte. Et queden <xliff:g id="NUMBER_1">%d</xliff:g> intents; si no l\'encertes, la SIM no es podrà tornar a fer servir.</item>
+ <item quantity="one">El codi PUK de la SIM no és correcte. Et queda <xliff:g id="NUMBER_0">%d</xliff:g> intent; si no l\'encertes, la SIM no es podrà tornar a fer servir.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Hi ha hagut un problema en l\'operació del PIN de la SIM."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Hi ha hagut un problema en l\'operació del PUK de la SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"S\'ha acceptat el codi."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sense servei."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
</resources>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index 138cec2..e1fa6f9 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g>dalších neúspěšných pokusech budete požádáni o odemčení tabletu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Již <xliff:g id="NUMBER_0">%d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Zadali jste nesprávný kód PIN SIM karty. Nyní musíte za účelem odemknutí zařízení kontaktovat svého operátora."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Zadali jste nesprávný kód PIN SIM karty. Máte ještě <xliff:g id="NUMBER">%d</xliff:g> pokus, poté budete muset o odemknutí zařízení požádat svého operátora."</item>
- <item quantity="other" msgid="2215723361575359486">"Zadali jste nesprávný kód PIN SIM karty. Počet zbývajících pokusů: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="few">Zadali jste nesprávný kód PIN SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item>
+ <item quantity="many">Zadali jste nesprávný kód PIN SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusu.</item>
+ <item quantity="other">Zadali jste nesprávný kód PIN SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusů.</item>
+ <item quantity="one">Zadali jste nesprávný PIN SIM karty. Zbývá <xliff:g id="NUMBER_0">%d</xliff:g> pokus, poté bude muset zařízení odemknout operátor.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM kartu nelze použít. Kontaktujte operátora."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Nesprávný kód PUK SIM karty. Máte ještě <xliff:g id="NUMBER">%d</xliff:g> pokus, poté bude SIM karta natrvalo zablokována."</item>
- <item quantity="other" msgid="5477305226026342036">"Zadali jste nesprávný kód PUK SIM karty. Počet zbývajících pokusů, po kterých bude SIM karta natrvalo zablokována: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="few">Nesprávný kód PUK SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusy, poté bude SIM karta natrvalo zablokována.</item>
+ <item quantity="many">Nesprávný kód PUK SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusu, poté bude SIM karta natrvalo zablokována.</item>
+ <item quantity="other">Nesprávný kód PUK SIM karty. Máte ještě <xliff:g id="NUMBER_1">%d</xliff:g> pokusů, poté bude SIM karta natrvalo zablokována.</item>
+ <item quantity="one">Nesprávný kód PUK SIM karty. Máte ještě <xliff:g id="NUMBER_0">%d</xliff:g> pokus, poté bude SIM karta natrvalo zablokována.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operace pomocí kódu PIN SIM karty se nezdařila!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operace pomocí kódu PUK SIM karty se nezdařila!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód byl přijat."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Žádný signál."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
</resources>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index a640dc4..77e8ce3 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg vil du blive bedt om at låse din tablet op ved hjælp af en e-mailkonto\n\n Prøv igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en e-mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Forkert pinkode til SIM-kort. Du skal nu kontakte dit mobilselskab for at låse din enhed op."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage, før du skal kontakte dit mobilselskab for at låse din enhed op."</item>
- <item quantity="other" msgid="2215723361575359486">"Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item>
+ <item quantity="other">Forkert pinkode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-kortet er ubrugeligt. Kontakt dit mobilselskab."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Forkert PUK-kode til SIM-kort. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt."</item>
- <item quantity="other" msgid="5477305226026342036">"Forkert PUK-kode til SIM-kort. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøg tilbage, før dit SIM-kort bliver permanent ubrugeligt."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Forkert PUK-kode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt.</item>
+ <item quantity="other">Forkert PUK-kode til SIM-kort. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøg tilbage, før SIM-kortet bliver permanent ubrugeligt.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Pinkoden til SIM-kortet blev afvist."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-koden til SIM-kortet blev afvist."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden blev accepteret."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen dækning."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
</resources>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index 466dbad..e21961d 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Tablet mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuchen Sie es in <xliff:g id="NUMBER_2">%d</xliff:g> Sekunden erneut."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Falscher PIN-Code der SIM-Karte. Bitte wenden Sie sich an Ihren Mobilfunkanbieter, damit er Ihr Gerät entsperrt."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Falscher PIN-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuch, bevor Sie das Gerät von Ihrem Mobilfunkanbieter entsperren lassen müssen."</item>
- <item quantity="other" msgid="2215723361575359486">"Falscher PIN-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuche."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Falscher PIN-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche.</item>
+ <item quantity="one">Falscher PIN-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER_0">%d</xliff:g> Versuch, bevor Sie das Gerät von Ihrem Mobilfunkanbieter entsperren lassen müssen.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Die SIM-Karte kann nicht verwendet werden. Bitte wenden Sie sich an Ihren Mobilfunkanbieter."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Falscher PUK-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuch, bevor Ihre SIM-Karte endgültig gesperrt wird."</item>
- <item quantity="other" msgid="5477305226026342036">"Falscher PUK-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER">%d</xliff:g> Versuche, bevor Ihre SIM-Karte endgültig gesperrt wird."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Falscher PUK-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche, bevor Ihre SIM-Karte endgültig gesperrt wird.</item>
+ <item quantity="one">Falscher PUK-Code der SIM-Karte. Sie haben noch <xliff:g id="NUMBER_0">%d</xliff:g> Versuch, bevor Ihre SIM-Karte endgültig gesperrt wird.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Fehler beim Entsperren mit der PIN der SIM-Karte"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Fehler beim Entsperren mithilfe des PUK-Codes der SIM-Karte"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code akzeptiert"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Kein Dienst"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
</resources>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index 3cae49c..7084c84 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το tablet σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε να συνδεθείτε ξανά σε <xliff:g id="NUMBER_2">%d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%d</xliff:g> δευτερόλεπτα."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Εσφαλμένος κωδικός PIN κάρτας SIM. Θα πρέπει να επικοινωνήσετε με τον πάροχο κινητής τηλεφωνίας σας για να ξεκλειδώσετε τη συσκευή σας."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Εσφαλμένος κωδικός PIN κάρτας SIM. Απομένει άλλη <xliff:g id="NUMBER">%d</xliff:g> προσπάθεια. Στη συνέχεια, θα πρέπει να επικοινωνήσετε με τον πάροχο κινητής τηλεφωνίας σας για να ξεκλειδώσετε τη συσκευή σας."</item>
- <item quantity="other" msgid="2215723361575359486">"Εσφαλμένος κωδικός PIN κάρτας SIM. Απομένουν <xliff:g id="NUMBER">%d</xliff:g> προσπάθειες."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Εσφαλμένος κωδικός PIN κάρτας SIM. Απομένουν άλλες <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες. </item>
+ <item quantity="one">Εσφαλμένος κωδικός PIN κάρτας SIM. Απομένει άλλη <xliff:g id="NUMBER_0">%d</xliff:g> προσπάθεια. Στη συνέχεια, θα πρέπει να επικοινωνήσετε με τον πάροχο κινητής τηλεφωνίας σας για να ξεκλειδώσετε τη συσκευή σας.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Η κάρτα SIM δεν μπορεί να χρησιμοποιηθεί. Επικοινωνήστε με τον πάροχο κινητής τηλεφωνίας σας."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Εσφαλμένος κωδικός PUK κάρτας SIM. Απομένει άλλη <xliff:g id="NUMBER">%d</xliff:g> προσπάθεια προτού δεν είναι πλέον δυνατή η χρήση της κάρτας SIM."</item>
- <item quantity="other" msgid="5477305226026342036">"Εσφαλμένος κωδικός PUK κάρτας SIM. Απομένουν <xliff:g id="NUMBER">%d</xliff:g> προσπάθειες προτού δεν είναι πλέον δυνατή η χρήση της κάρτας SIM."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Εσφαλμένος κωδικός PUK κάρτας SIM. Απομένουν άλλες <xliff:g id="NUMBER_1">%d</xliff:g> προσπάθειες προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM.</item>
+ <item quantity="one">Εσφαλμένος κωδικός PUK κάρτας SIM. Απομένει άλλη <xliff:g id="NUMBER_0">%d</xliff:g> προσπάθεια προτού να μην είναι πλέον δυνατή η χρήση της κάρτας SIM.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Αποτυχία λειτουργίας κωδικού PIN κάρτας SIM!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Αποτυχία λειτουργίας κωδικού PUK κάρτας SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Αποδεκτός κωδικός!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Καμία υπηρεσία."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</string>
</resources>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index ab4f7e8..ee5da13 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Incorrect SIM PIN code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before you must contact your carrier to unlock your device."</item>
- <item quantity="other" msgid="2215723361575359486">"Incorrect SIM PIN code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM is unusable. Contact your operator."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Incorrect SIM PUK code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM becomes permanently unusable."</item>
- <item quantity="other" msgid="5477305226026342036">"Incorrect SIM PUK code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM becomes permanently unusable."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
+ <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN operation failed!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK operation failed!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
</resources>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index ab4f7e8..ee5da13 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your tablet using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Incorrect SIM PIN code; you must now contact your operator to unlock your device."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Incorrect SIM PIN code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before you must contact your carrier to unlock your device."</item>
- <item quantity="other" msgid="2215723361575359486">"Incorrect SIM PIN code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
+ <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before you must contact your operator to unlock your device.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM is unusable. Contact your operator."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Incorrect SIM PUK code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM becomes permanently unusable."</item>
- <item quantity="other" msgid="5477305226026342036">"Incorrect SIM PUK code; you have <xliff:g id="NUMBER">%d</xliff:g> remaining attempt/s before SIM becomes permanently unusable."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
+ <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_0">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN operation failed!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK operation failed!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
</resources>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index 8afbd13..b34dd05 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu tablet mediante el uso de una cuenta de correo.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"El código PIN de la tarjeta SIM es incorrecto. Debes comunicarte con el proveedor para desbloquear el dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"El código PIN de la tarjeta SIM es incorrecto. Te queda <xliff:g id="NUMBER">%d</xliff:g> intento antes de que debas comunicarte con el proveedor para desbloquear el dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"El código PIN de la tarjeta SIM es incorrecto. Te quedan <xliff:g id="NUMBER">%d</xliff:g> intentos."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">El código PIN de la tarjeta SIM es incorrecto. Tienes <xliff:g id="NUMBER_1">%d</xliff:g> intentos más.</item>
+ <item quantity="one">El código PIN de la tarjeta SIM es incorrecto. Tienes <xliff:g id="NUMBER_0">%d</xliff:g> intento más antes de que debas comunicarte con el proveedor para desbloquear el dispositivo.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"La tarjeta SIM no se puede utilizar. Comunícate con el proveedor."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"El código PUK de la tarjeta SIM es incorrecto. Te queda <xliff:g id="NUMBER">%d</xliff:g> intento antes de que la tarjeta SIM quede inutilizable permanentemente."</item>
- <item quantity="other" msgid="5477305226026342036">"El código PUK de la tarjeta SIM es incorrecto. Te quedan <xliff:g id="NUMBER">%d</xliff:g> intentos antes de que la tarjeta SIM quede inutilizable permanentemente."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">El código PUK de la tarjeta SIM es incorrecto. Tienes <xliff:g id="NUMBER_1">%d</xliff:g> intentos más antes de que la tarjeta SIM quede inutilizable de forma permanente.</item>
+ <item quantity="one">El código PUK de la tarjeta SIM es incorrecto. Tienes <xliff:g id="NUMBER_0">%d</xliff:g> intento más antes de que la tarjeta SIM quede inutilizable de forma permanente.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Error al desbloquear la tarjeta SIM con el PIN"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Error al desbloquear la tarjeta SIM con el PUK"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
</resources>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index d8c548b..be3c113 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Has fallado <xliff:g id="NUMBER_0">%d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el tablet.\n\n Inténtalo de nuevo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Has fallado <xliff:g id="NUMBER_0">%d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el teléfono.\n\n Inténtalo de nuevo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Código PIN de la tarjeta SIM incorrecto. Debes ponerte en contacto con tu operador para desbloquear el dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Código PIN de la tarjeta SIM incorrecto. Queda <xliff:g id="NUMBER">%d</xliff:g> intento para tener que ponerte en contacto con tu operador para desbloquear el dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"Código PIN de la tarjeta SIM incorrecto. Quedan <xliff:g id="NUMBER">%d</xliff:g> intentos."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Código PIN de la tarjeta SIM incorrecto. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item>
+ <item quantity="one">Código PIN de la tarjeta SIM incorrecto. Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento para tener que ponerte en contacto con tu operador para desbloquear el dispositivo.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"La tarjeta SIM no se puede utilizar. Ponte en contacto con tu operador."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Código PUK de la tarjeta SIM incorrecto. Te queda <xliff:g id="NUMBER">%d</xliff:g> intento para que la tarjeta SIM no se pueda utilizar de forma permanente."</item>
- <item quantity="other" msgid="5477305226026342036">"Código PUK de la tarjeta SIM incorrecto. Quedan <xliff:g id="NUMBER">%d</xliff:g> intentos para que la tarjeta SIM no se pueda utilizar de forma permanente."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Código PUK de la tarjeta SIM incorrecto. Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos para que la tarjeta SIM no se pueda utilizar de forma permanente.</item>
+ <item quantity="one">Código PUK de la tarjeta SIM incorrecto. Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento para que la tarjeta SIM no se pueda utilizar de forma permanente.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Error al intentar desbloquear la tarjeta SIM con el código PIN"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Error al intentar desbloquear la tarjeta SIM con el código PUK"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
</resources>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 55e6a97..402fc14 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset palutakse teil tahvelarvuti avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%d</xliff:g> sekundi pärast."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%d</xliff:g> sekundi pärast."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Vale SIM-i PIN-kood, seadme avamiseks peate nüüd ühendust võtma oma operaatoriga."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Vale SIM-i PIN-kood, teil on jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katse, enne kui peate seadme avamiseks operaatoriga ühendust võtma."</item>
- <item quantity="other" msgid="2215723361575359486">"Vale SIM-i PIN-kood, teil on jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katset."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Vale SIM-kaardi PIN-kood, teil on jäänud veel <xliff:g id="NUMBER_1">%d</xliff:g> katset.</item>
+ <item quantity="one">Vale SIM-kaardi PIN-kood, teil on jäänud veel <xliff:g id="NUMBER_0">%d</xliff:g> katse enne, kui peate seadme avamiseks operaatoriga ühendust võtma.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM ei ole kasutatav. Võtke ühendust operaatoriga."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Vale SIM-i PUK-kood, teil on jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katse, enne kui SIM püsivalt lukustatakse."</item>
- <item quantity="other" msgid="5477305226026342036">"Vale SIM-i PUK-kood, teil on jäänud veel <xliff:g id="NUMBER">%d</xliff:g> katset, enne kui SIM püsivalt lukustatakse."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Vale SIM-kaardi PUK-kood, teil on jäänud veel <xliff:g id="NUMBER_1">%d</xliff:g> katset enne, kui SIM-kaart püsivalt lukustatakse.</item>
+ <item quantity="one">Vale SIM-kaardi PUK-kood, teil on jäänud veel <xliff:g id="NUMBER_0">%d</xliff:g> katse enne, kui SIM-kaart püsivalt lukustatakse.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM-i PIN-koodi toiming ebaõnnestus."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-i PUK-koodi toiming ebaõnnestus."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kood on õige."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Teenus puudub."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
</resources>
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index ba07523..86850bb 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%d</xliff:g> aldiz oker marrazten baduzu, tableta posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%d</xliff:g> segundo barru."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%d</xliff:g> segundo barru."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM txartelaren PIN kodea okerra da. Gailua desblokeatzeko, jarri operadorearekin harremanetan."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM txartelaren PIN kodea ez da zuzena; <xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizu. Saiakerak agortuz gero, operadoreari eskatu beharko diozu gailua desblokeatzeko."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM txartelaren PIN kodea ez da zuzena; <xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizkizu."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM txartelaren PIN kodea okerra da. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu gailua desblokeatzeko.</item>
+ <item quantity="one">SIM txartelaren PIN kodea okerra da. <xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu gailua desblokeatzeko.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM txartela erabilgaitza da. Jarri operadorearekin harremanetan."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM txartelaren PUK kodea ez da zuzena; <xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizu SIM txartela betiko erabilgaitz geratu aurretik."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM txartelaren PUK kodea ez da zuzena; <xliff:g id="NUMBER">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela betiko erabilgaitz geratu aurretik."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM txartelaren PUK kodea okerra da. <xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela betiko erabilgaitz geratu aurretik.</item>
+ <item quantity="one">SIM txartelaren PUK kodea okerra da. <xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela betiko erabilgaitz geratu aurretik.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM txartelaren PIN eragiketak huts egin du!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM txartelaren PUK eragiketak huts egin du!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodea onartu da!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Zerbitzurik gabe."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Idazketa-metodoa aldatzeko botoia."</string>
</resources>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index c41a3d6..b297f09 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که با استفاده از یک حساب ایمیل قفل رایانه لوحی خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیدهاید. پس از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته میشود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"کد پین سیم کارت اشتباه است، اکنون برای گشودن قفل دستگاهتان باید با شرکت مخابراتی تماس بگیرید."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"کد پین سیم کارت اشتباه است، <xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن برای گشودن قفل دستگاهتان باید با شرکت مخابراتی تماس بگیرید."</item>
- <item quantity="other" msgid="2215723361575359486">"کد پین سیم کارت اشتباه است، <xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <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="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"سیم کارت غیر قابل استفاده است. با شرکت مخابراتیتان تماس بگیرید."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"کد PUK سیم کارت اشتباه است، <xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیم کارت به صورت دائم غیر قابل استفاده میشود."</item>
- <item quantity="other" msgid="5477305226026342036">"کد PUK سیم کارت اشتباه است، <xliff:g id="NUMBER">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیم کارت به طور دائم غیر قابل استفاده میشود."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">کد PUK سیمکارت اشتباه است، <xliff:g id="NUMBER_1">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیمکارت به صورت دائم غیر قابل استفاده میشود.</item>
+ <item quantity="other">کد PUK سیمکارت اشتباه است، <xliff:g id="NUMBER_1">%d</xliff:g> بار دیگر میتوانید تلاش کنید و پس از آن سیمکارت به صورت دائم غیر قابل استفاده میشود.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"عملیات پین سیم کارت ناموفق بود!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"عملیات PUK سیم کارت ناموفق بود!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"کد پذیرفته شد!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"خدماتی وجود ندارد."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</string>
</resources>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index 8485cbe..68f7016 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan tablet-laitteesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Virheellinen SIM-kortin PIN-koodi. Sinun on nyt otettava yhteys operaattoriin laitteen lukituksen avaamiseksi."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Virheellinen SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritys jäljellä, ennen kuin sinun on otettava yhteys operaattoriin laitteen lukituksen avaamiseksi."</item>
- <item quantity="other" msgid="2215723361575359486">"Virheellinen SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritystä jäljellä."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Virheellinen SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER_1">%d</xliff:g> yritystä jäljellä.</item>
+ <item quantity="one">Virheellinen SIM-kortin PIN-koodi. Sinulla on <xliff:g id="NUMBER_0">%d</xliff:g> yritys jäljellä, ennen kuin sinun on otettava yhteyttä operaattoriin laitteen lukituksen avaamiseksi.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-kortti on käyttökelvoton. Ota yhteys operaattoriin."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Virheellinen SIM-kortin PUK-koodi. Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortista tulee pysyvästi käyttökelvoton."</item>
- <item quantity="other" msgid="5477305226026342036">"Virheellinen SIM-kortin PUK-koodi. Sinulla on <xliff:g id="NUMBER">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortista tulee pysyvästi käyttökelvoton."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Virheellinen SIM-kortin PUK-koodi. Sinulla on <xliff:g id="NUMBER_1">%d</xliff:g> yritystä jäljellä, ennen kuin SIM-kortista tulee pysyvästi käyttökelvoton.</item>
+ <item quantity="one">Virheellinen SIM-kortin PUK-koodi. Sinulla on <xliff:g id="NUMBER_0">%d</xliff:g> yritys jäljellä, ennen kuin SIM-kortista tulee pysyvästi käyttökelvoton.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM-kortin PIN-toiminto epäonnistui!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-kortin PUK-toiminto epäonnistui!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koodi hyväksytty!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ei yhteyttä."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
</resources>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index e45f7f4..2c24f7a 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"NIP de carte SIM incorrect. Vous devez maintenant communiquer avec votre fournisseur de services pour déverrouiller votre appareil."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"NIP de carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative. Après cela, vous devrez communiquer avec votre fournisseur de services pour déverrouiller votre appareil."</item>
- <item quantity="other" msgid="2215723361575359486">"NIP de carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative(s)."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Le NIP de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
+ <item quantity="other">Le NIP de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"La carte SIM est inutilisable. Communiquez avec votre fournisseur de services."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Code PUK de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable."</item>
- <item quantity="other" msgid="5477305226026342036">"Code PUK de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative(s) avant que votre carte SIM devienne définitivement inutilisable."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Le code PUK de la carte SIM est incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable.</item>
+ <item quantity="other">Le code PUK de la carte SIM est incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM devienne définitivement inutilisable.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Le déverrouillage par NIP de la carte SIM a échoué."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Le déverrouillage de la carte SIM par code PUK a échoué."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
</resources>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index a87da9a..77a2d06 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre tablette à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Code PIN de la carte SIM incorrect. Vous devez désormais contacter votre opérateur pour déverrouiller votre appareil."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Code PIN de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative. Après cela, vous devrez contacter votre opérateur pour déverrouiller votre appareil."</item>
- <item quantity="other" msgid="2215723361575359486">"Code PIN de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentatives."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Code PIN de la carte SIM erroné. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
+ <item quantity="other">Code PIN de la carte SIM erroné. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"La carte SIM est inutilisable. Veuillez contacter votre opérateur."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Clé PUK de la carte SIM incorrecte. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable."</item>
- <item quantity="other" msgid="5477305226026342036">"Clé PUK de la carte SIM incorrecte. Il vous reste <xliff:g id="NUMBER">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Clé PUK de la carte SIM erronée. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable.</item>
+ <item quantity="other">Clé PUK de la carte SIM erronée. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Échec du déverrouillage à l\'aide du code PIN de la carte SIM."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Échec du déverrouillage à l\'aide de la clé PUK de la carte SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
</resources>
diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml
index 1a5595a..8e8f5c5 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos máis, terás que desbloquear o tablet a través dunha unha conta de correo electrónico.\n\n Téntao de novo dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"O código PIN da SIM non é correcto. Agora debes contactar co teu operador para desbloquear o dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"O código PIN da SIM non é correcto. Quédache <xliff:g id="NUMBER">%d</xliff:g> intento antes de que teñas que contactar co operador para desbloquear o dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"O código PIN da SIM non é correcto. Quédanche <xliff:g id="NUMBER">%d</xliff:g> intentos."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">O código PIN da SIM é incorrecto. Quédanche <xliff:g id="NUMBER_1">%d</xliff:g> intentos.</item>
+ <item quantity="one">O código PIN da SIM é incorrecto. Quédache <xliff:g id="NUMBER_0">%d</xliff:g> intento antes de que teñas que contactar co operador para desbloquear o dispositivo.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"A SIM está inutilizable. Contacta co teu operador."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"O código PUK da SIM non é correcto. Quédache <xliff:g id="NUMBER">%d</xliff:g> intento antes de que a SIM quede inutilizable para sempre."</item>
- <item quantity="other" msgid="5477305226026342036">"O código PUK da SIM non é correcto. Quédanche <xliff:g id="NUMBER">%d</xliff:g> intentos antes de que a SIM quede inutilizable para sempre."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">O código PUK da SIM é incorrecto. Quédanche <xliff:g id="NUMBER_1">%d</xliff:g> intentos antes de que a SIM quede inutilizable para sempre.</item>
+ <item quantity="one">O código PUK da SIM é incorrecto. Quédache <xliff:g id="NUMBER_0">%d</xliff:g> intento antes de que a SIM quede inutilizable para sempre.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Erro ao tentar desbloquear a tarxeta SIM co código PIN."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Erro ao tentar desbloquar a tarxeta SIM co código PUK."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Non hai servizo."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Cambiar o botón do método de entrada."</string>
</resources>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 788891e..0cd65b8 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"गलत सिम PIN कोड अपने डिवाइस को अनलॉक करने के लिए अब आपको अपने वाहक से संपर्क करना होगा."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"गलत सिम PIN कोड, अपने डिवाइस को अनलॉक करने के लिए अपने वाहक से संपर्क करने से पहले आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष है."</item>
- <item quantity="other" msgid="2215723361575359486">"गलत सिम PIN कोड, आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष हैं."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">गलत सिम PIN कोड, आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> प्रयास शेष हैं.</item>
+ <item quantity="other">गलत सिम PIN कोड, आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> प्रयास शेष हैं.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"सिम अनुपयोगी है. अपने वाहक से संपर्क करें."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"गलत सिम PUK कोड, सिम के स्थायी रूप से अनुपयोगी हो जाने से पहले आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष है."</item>
- <item quantity="other" msgid="5477305226026342036">"गलत सिम PUK कोड, सिम के स्थायी रूप से अनुपयोगी हो जाने से पहले आपके पास <xliff:g id="NUMBER">%d</xliff:g> प्रयास शेष हैं."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">गलत सिम PUK कोड, सिम के स्थायी रूप से अनुपयोगी हो जाने से पहले आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> प्रयास शेष हैं.</item>
+ <item quantity="other">गलत सिम PUK कोड, सिम के स्थायी रूप से अनुपयोगी हो जाने से पहले आपके पास <xliff:g id="NUMBER_1">%d</xliff:g> प्रयास शेष हैं.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"सिम PIN की कार्यवाही विफल रही!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"सिम PUK की कार्यवाही विफल रही!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकार किया गया!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"कोई सेवा नहीं."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति बटन स्विच करें."</string>
</resources>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index c659e5d..71410c5 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -95,17 +95,20 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati tabletno računalo pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Netočan PIN kôd SIM kartice; sada morate kontaktirati svog mobilnog operatera da bi otključao vaš uređaj."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Netočan PIN kôd SIM kartice; imate još <xliff:g id="NUMBER">%d</xliff:g> pokušaj prije nego što budete morali kontaktirati svog mobilnog operatera da bi otključao vaš uređaj."</item>
- <item quantity="other" msgid="2215723361575359486">"Netočan PIN kôd SIM kartice; imate još ovoliko preostalih pokušaja: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Netočan PIN kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj.</item>
+ <item quantity="few">Netočan PIN kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item>
+ <item quantity="other">Netočan PIN kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM kartica nije upotrebljiva. Kontaktirajte svog mobilnog operatera."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Netočan PUK kôd SIM kartice; imate još <xliff:g id="NUMBER">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva."</item>
- <item quantity="other" msgid="5477305226026342036">"Netočan PUK kôd SIM kartice; imate još nekoliko preostalih pokušaja (<xliff:g id="NUMBER">%d</xliff:g>) prije nego što SIM kartica postane trajno neupotrebljiva."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Netočan PUK kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaj prije nego što SIM kartica postane trajno neupotrebljiva.</item>
+ <item quantity="few">Netočan PUK kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva.</item>
+ <item quantity="other">Netočan PUK kôd SIM kartice; imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operacija PIN-a SIM kartice nije uspjela!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operacija PUK-a SIM kartice nije uspjela!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kôd je prihvaćen!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nema usluge."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
</resources>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index 144e76d..dd43dba 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a táblagépét.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Helytelen PIN kód a SIM kártyához; vegye fel a kapcsolatot szolgáltatójával az eszköz feloldásához."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Helytelen PIN kód a SIM kártyához; még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van, mielőtt fel kellene vennie a kapcsolatot szolgáltatójával az eszköz feloldásához."</item>
- <item quantity="other" msgid="2215723361575359486">"Helytelen PIN kód a SIM kártyához; még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">A SIM kártya PIN kódja helytelen. <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozás maradt.</item>
+ <item quantity="one">A SIM kártya PIN kódja helytelen. <xliff:g id="NUMBER_0">%d</xliff:g> próbálkozás maradt. Utána a szolgáltatótól kell feloldást kérnie.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"A SIM kártya használhatatlan. Vegye fel a kapcsolatot szolgáltatójával."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Helytelen PUK kód a SIM kártyához; még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van, mielőtt a SIM kártya végleg használhatatlan lesz."</item>
- <item quantity="other" msgid="5477305226026342036">"Helytelen PUK kód a SIM kártyához; még <xliff:g id="NUMBER">%d</xliff:g> próbálkozása van, mielőtt a SIM kártya végleg használhatatlan lesz."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Helytelen PUK kód a SIM kártyához. Még <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozása van, mielőtt a SIM kártya végleg használhatatlanná válik.</item>
+ <item quantity="one">Helytelen PUK kód a SIM kártyához. Még <xliff:g id="NUMBER_0">%d</xliff:g> próbálkozása van, mielőtt a SIM kártya végleg használhatatlanná válik.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"A SIM kártya PIN-művelete sikertelen!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"A SIM kártya PUK-művelete sikertelen!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód elfogadva."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nincs szolgáltatás."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
</resources>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index 1c9c8a0..e56642a 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Դուք սխալ եք հավաքել ձեր ապակողպման սխեման <xliff:g id="NUMBER_0">%d</xliff:g> անգամ: Եվս <xliff:g id="NUMBER_1">%d</xliff:g> անհաջող փորձից հետո ձեզանից կպահանջվի ապակողպել ձեր գրասալիկը` օգտագործելով էլփոստի հաշիվ:\n\n Փորձեք կրկին <xliff:g id="NUMBER_2">%d</xliff:g> վայրկյանից:"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Դուք <xliff:g id="NUMBER_0">%d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: <xliff:g id="NUMBER_1">%d</xliff:g> անգամից ավել անհաջող փորձերից հետո ձեզ կառաջարկվի ապակողպել ձեր հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Փորձեք կրկին <xliff:g id="NUMBER_2">%d</xliff:g> վայրկյանից:"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Սխալ SIM PIN կոդի պատճառով պետք է դիմեք ձեր օպերատորին՝ սարքն արգելաբացելու համար:"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN կոդը սխալ է: Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ, որից հետո պետք է դիմեք ձեր օպերատորին՝ սարքն արգելաբացելու համար:"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN կոդը սխալ է: Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ:"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">SIM PIN կոդը սխալ է: Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ:</item>
+ <item quantity="other">SIM PIN կոդը սխալ է: Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ:</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-ը հնարավոր չէ օգտագործել: Դիմեք ձեր օպերատորին:"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK կոդը սխալ է: Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ՝ մինչև SIM-ի ընդմիշտ արգելափակումը:"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK կոդը սխալ է: Մնաց <xliff:g id="NUMBER">%d</xliff:g> փորձ՝ մինչև SIM-ի ընդմիշտ արգելափակումը:"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">SIM PUK կոդը սխալ է: Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել:</item>
+ <item quantity="other">SIM PUK կոդը սխալ է: Մնաց <xliff:g id="NUMBER_1">%d</xliff:g> փորձ, որից հետո SIM քարտն այլևս հնարավոր չի լինի օգտագործել:</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN գործողությունը ձախողվեց:"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK գործողությունը ձախողվեց:"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Կոդն ընդունվեց:"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ծառայություն չկա:"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
</resources>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index 6539cc1..29a56ef 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci tablet menggunakan akun email.\n\nCoba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\nCoba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Kode PIN SIM salah. Hubungi operator untuk membuka kunci perangkat."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Kode PIN SIM salah, sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan sebelum Anda harus menghubungi operator untuk membuka kunci perangkat."</item>
- <item quantity="other" msgid="2215723361575359486">"Kode PIN SIM salah, sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Kode PIN SIM salah, sisa <xliff:g id="NUMBER_1">%d</xliff:g> percobaan.</item>
+ <item quantity="one">Kode PIN SIM salah, sisa <xliff:g id="NUMBER_0">%d</xliff:g> percobaan sebelum Anda harus menghubungi operator untuk membuka kunci perangkat.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM tidak dapat digunakan. Hubungi operator Anda."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Kode PUK SIM salah, sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan selamanya."</item>
- <item quantity="other" msgid="5477305226026342036">"Kode PUK SIM salah, sisa <xliff:g id="NUMBER">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan selamanya."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Kode PUK SIM salah, sisa <xliff:g id="NUMBER_1">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan selamanya.</item>
+ <item quantity="one">Kode PUK SIM salah, sisa <xliff:g id="NUMBER_0">%d</xliff:g> percobaan sebelum SIM tidak dapat digunakan selamanya.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operasi PIN SIM gagal!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operasi PUK SIM gagal!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kode Diterima!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Tidak ada layanan."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
</resources>
diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml
index 4037533..5741cd0 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna spjaldtölvuna með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%d</xliff:g> sekúndur."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%d</xliff:g> sekúndur."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Rangt PIN-númer SIM-korts. Þú þarft núna að hafa samband við símafyrirtækið þitt til að taka tækið úr lás."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Rangt PIN-númer SIM-korts. Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraun eftir áður en þú þarft að hafa samband við símafyrirtækið þitt til að taka tækið úr lás."</item>
- <item quantity="other" msgid="2215723361575359486">"Rangt PIN-númer SIM-korts. Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraunir eftir."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Rangt PIN-númer SIM-korts. Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraun eftir.</item>
+ <item quantity="other">Rangt PIN-númer SIM-korts. Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraunir eftir.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-kortið er ónothæft. Hafðu samband við símafyrirtækið þitt."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Rangt PUK-númer SIM-korts. Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraun eftir áður en SIM-kortið verður ónothæft til frambúðar."</item>
- <item quantity="other" msgid="5477305226026342036">"Rangt PUK-númer SIM-korts. Þú átt <xliff:g id="NUMBER">%d</xliff:g> tilraunir eftir áður en SIM-kortið verður ónothæft til frambúðar."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Rangt PUK-númer SIM-korts. Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraun eftir áður en SIM-kortið verður ónothæft til frambúðar.</item>
+ <item quantity="other">Rangt PUK-númer SIM-korts. Þú átt <xliff:g id="NUMBER_1">%d</xliff:g> tilraunir eftir áður en SIM-kortið verður ónothæft til frambúðar.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"PIN-aðgerð SIM-korts mistókst!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-aðgerð SIM-korts mistókst!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Númer samþykkt!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ekkert símasamband."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Hnappur til að skipta um innsláttaraðferð."</string>
</resources>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index 3b8fdd7..c5c476c 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il tablet con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%d</xliff:g> secondi."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%d</xliff:g> secondi."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativi a disposizione."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
+ <item quantity="one">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM inutilizzabile. Contatta il tuo operatore."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile."</item>
- <item quantity="other" msgid="5477305226026342036">"Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
+ <item quantity="one">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operazione con PIN della SIM non riuscita."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operazione con PUK della SIM non riuscita."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Codice accettato."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nessun servizio."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
</resources>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index 3f66c83..a856ccb 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטאבלט באמצעות חשבון אימייל.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"מספר PIN שגוי של כרטיס ה-SIM. עליך ליצור כעת קשר עם הספק על מנת לבטל את נעילת המכשיר."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"מספר PIN שגוי של כרטיס ה-SIM. נותר לך ניסיון <xliff:g id="NUMBER">%d</xliff:g> נוסף לפני שיהיה עליך ליצור קשר עם הספק על מנת לבטל את נעילת המכשיר."</item>
- <item quantity="other" msgid="2215723361575359486">"מספר PIN שגוי של כרטיס ה-SIM. נותרו לך <xliff:g id="NUMBER">%d</xliff:g> ניסיונות נוספים."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="two">קוד PIN שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+ <item quantity="many">קוד PIN שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+ <item quantity="other">קוד PIN שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות.</item>
+ <item quantity="one">קוד PIN שגוי של כרטיס SIM. נותר לך ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> לפני שיהיה עליך ליצור קשר עם הספק כדי לבטל את נעילת המכשיר.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"לא ניתן להשתמש בכרטיס ה-SIM. צור קשר עם הספק."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"קוד PUK שגוי של כרטיס ה-SIM. נותר לך ניסיון <xliff:g id="NUMBER">%d</xliff:g> נוסף לפני שכרטיס ה-SIM ינעל לצמיתות."</item>
- <item quantity="other" msgid="5477305226026342036">"קוד PUK שגוי של כרטיס ה-SIM. נותרו לך <xliff:g id="NUMBER">%d</xliff:g> ניסיונות נוספים לפני שכרטיס ה-SIM ינעל לצמיתות."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="two">קוד PUK שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני שכרטיס ה-SIM יינעל לצמיתות.</item>
+ <item quantity="many">קוד PUK שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני שכרטיס ה-SIM יינעל לצמיתות.</item>
+ <item quantity="other">קוד PUK שגוי של כרטיס SIM. נותרו לך <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות לפני שכרטיס ה-SIM יינעל לצמיתות.</item>
+ <item quantity="one">קוד PUK שגוי של כרטיס SIM. נותר לך ניסיון <xliff:g id="NUMBER_0">%d</xliff:g> לפני שכרטיס ה-SIM יינעל לצמיתות.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"פעולת מספר ה-PIN של כרטיס ה-SIM נכשלה!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"פעולת קוד ה-PUK של כרטיס ה-SIM נכשלה!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"הקוד התקבל!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"אין קליטה."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index 1628099..5c76034 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、タブレットのロック解除にメールアカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%d</xliff:g>回間違えると、携帯端末のロック解除にメールアカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%d</xliff:g>秒後にもう一度お試しください。"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PINコードが無効です。お使いの端末をロック解除するには携帯通信会社にお問い合わせいただく必要があります。"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PINコードが無効です。入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。この回数を超えると、お使いの端末をロック解除するのに携帯通信会社にお問い合わせいただく必要があります。"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PINコードが無効です。入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PINコードが無効です。入力できるのはあと<xliff:g id="NUMBER_1">%d</xliff:g>回です。</item>
+ <item quantity="one">SIM PINコードが無効です。入力できるのはあと<xliff:g id="NUMBER_0">%d</xliff:g>回です。この回数を超えた場合は、携帯通信会社にお問い合わせください。</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIMは使用できません。携帯通信会社にお問い合わせください。"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUKコードが無効です。入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。この回数を超えるとSIMは完全に使用できなくなります。"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUKコードが無効です。入力できるのはあと<xliff:g id="NUMBER">%d</xliff:g>回です。この回数を超えるとSIMは完全に使用できなくなります。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUKコードが無効です。入力できるのはあと<xliff:g id="NUMBER_1">%d</xliff:g>回です。この回数を超えるとSIMは完全に使用できなくなります。</item>
+ <item quantity="one">SIM PUKコードが無効です。入力できるのはあと<xliff:g id="NUMBER_0">%d</xliff:g>回です。この回数を超えるとSIMは完全に使用できなくなります。</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN操作に失敗しました。"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK操作に失敗しました。"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"コードが承認されました。"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"通信サービスはありません。"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</string>
</resources>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index 6060ba7..e9c77fd 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%d</xliff:g> ჯერ. კიდევ <xliff:g id="NUMBER_1">%d</xliff:g> წარუმატებელი ცდის შემდეგ მოგთხოვთ ტაბლეტის განბლოკვას ელფოსტის ანგარიშის გამოყენებით.\n\n ხელახლა სცადეთ <xliff:g id="NUMBER_2">%d</xliff:g> წამში."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%d</xliff:g> წარუმატებელი ცდის შემდეგ, დაგჭირდებათ თქვენი ტელეფონის განბლოკვა ელფოსტის ანგარიშის გამოყენებით.\n\n ხელახლა სცადეთ <xliff:g id="NUMBER_2">%d</xliff:g> წამში."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM-ის არასწორი PIN კოდი. თქვენ ახლა მოგიწევთ მოწყობილობის განსაბლოკად მიმართოთ ოპერატორს."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM-ის არასწორი PIN კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა, სანამ მოგიწევთ თქვენი მოწყობილობის განსაბლოკად ოპერატორთან დაკავშირება."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM-ის არასწორი PIN კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM-ის PIN კოდი არასწორია. თქვენ დაგრჩათ <xliff:g id="NUMBER_1">%d</xliff:g> მცდელობა.</item>
+ <item quantity="one">SIM-ის PIN კოდი არასწორია. თქვენ დაგრჩათ <xliff:g id="NUMBER_0">%d</xliff:g> მცდელობა, სანამ მოგიწევთ თქვენი მოწყობილობის განსაბლოკად ოპერატორთან დაკავშირება.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM გამოუსადეგარია. დაუკავშირდით ოპერატორს."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"არასწორი SIM PUK კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდებოდეს."</item>
- <item quantity="other" msgid="5477305226026342036">"არასწორი SIM PUK კოდი. თქვენ დაგრჩათ <xliff:g id="NUMBER">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდებოდეს."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM-ის PUK კოდი არასწორია. თქვენ დაგრჩათ <xliff:g id="NUMBER_1">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება.</item>
+ <item quantity="one">SIM-ის PUK კოდი არასწორია. თქვენ დაგრჩათ <xliff:g id="NUMBER_0">%d</xliff:g> მცდელობა, სანამ SIM სამუდამოდ გამოუსადეგარი გახდება.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN ოპერაცია ჩაიშალა!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ოპერაცია ჩაიშალა!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"კოდი მიღებულია!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"არ არის სერვისი."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
</resources>
diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml
index 460b923..85443f6 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%d</xliff:g> рет қате сыздыңыз. After <xliff:g id="NUMBER_1">%d</xliff:g> сәтсіз әрекеттен кейін планшетіңізді есептік жазба арқылы ашу өтінішін аласыз.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN коды дұрыс емес, құрылғыны ашу үшін қызмет жабдықтаушыға хабарласаңыз."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN коды дұрыс емес, құрылғыны жабу өтінішімен жабдықтаушыға хабарласуға дейін <xliff:g id="NUMBER">%d</xliff:g> рет әрекеттену мүмкіндігіңіз бар."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN коды дұрыс емес, <xliff:g id="NUMBER">%d</xliff:g> рет әрекеттену мүмкіндігіңіз қалды."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN коды дұрыс емес, <xliff:g id="NUMBER_1">%d</xliff:g> әрекет қалды.</item>
+ <item quantity="one">SIM PIN коды дұрыс емес, операторға құрылғы бекітпесін ашуы үшін хабарласуға дейін <xliff:g id="NUMBER_0">%d</xliff:g> әрекет қалды.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM қолданыстан шыққан. Қызмет жабдықтаушыға хабарласыңыз."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PIN коды дұрыс емес, <xliff:g id="NUMBER">%d</xliff:g> әрекеттен кейін SIM қолданыстан мүлдем шығады."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK коды дұрыс емес, <xliff:g id="NUMBER">%d</xliff:g> әрекеттен кейін SIM қолданыстан мүлдем шығады."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK коды дұрыс емес, SIM біржола пайдалануға жарамсыз болуына <xliff:g id="NUMBER_1">%d</xliff:g> әрекет қалды.</item>
+ <item quantity="one">SIM PUK коды дұрыс емес, SIM біржола пайдалануға жарамсыз болуына <xliff:g id="NUMBER_0">%d</xliff:g> әрекет қалды.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN жұмысы орындалмады!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK жұмысы орындалмады!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код қабылданды!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Қызмет көрсетілмейді."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Енгізу әдісі түймесін ауыстыру."</string>
</resources>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index e8e24fb5..be72fd6 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"អ្នកបានគូរលំនាំដោះសោមិនត្រឹមត្រូវ <xliff:g id="NUMBER_0">%d</xliff:g> ដង។ បន្ទាប់ពីការព្យាយាម <xliff:g id="NUMBER_1">%d</xliff:g> ដងមិនជោគជ័យ អ្នកនឹងត្រូវបានស្នើឲ្យដោះសោកុំព្យូទ័របន្ទះរបស់អ្នក ដោយប្រើគណនីអ៊ីមែល។\n\n ព្យាយាមម្ដងទៀតក្នុងរយៈពេល <xliff:g id="NUMBER_2">%d</xliff:g> វិនាទី។"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"អ្នកបានគូរលំនាំដោះសោរបស់អ្នកមិនត្រឹមត្រូវចំនួន <xliff:g id="NUMBER_0">%d</xliff:g> ដង។ បន្ទាប់ពីការព្យាយាមមិនជោគជ័យច្រើនជាង <xliff:g id="NUMBER_1">%d</xliff:g> ដង អ្នកនឹងត្រូវបានស្នើឲ្យដោះសោទូរស័ព្ទរបស់អ្នកដោយប្រើគណនីអ៊ីមែល។\n\n ព្យាយាមម្ដងទៀតក្នុងរយៈពេល <xliff:g id="NUMBER_2">%d</xliff:g> វិនាទី។"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"លេខកូដ PIN ស៊ីមមិនត្រឹមត្រូវ អ្នកត្រូវទាក់ទងក្រុមហ៊ុនបញ្ជូនរបស់អ្នកឥឡូវនេះ ដើម្បីដោះសោឧបករណ៍របស់អ្នក។"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"លេខកូដ PIN ស៊ីមមិនត្រឹមត្រូវ, អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់មុនពេលអ្នកត្រូវទាក់ទងក្រុមហ៊ុនបញ្ជូនរបស់អ្នក ដើម្បីដោះសោឧបករណ៍របស់អ្នក។"</item>
- <item quantity="other" msgid="2215723361575359486">"លេខកូដ PIN ស៊ីមមិនត្រឹមត្រូវ, អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់។"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">លេខកូដសម្ងាត់ស៊ីមមិនត្រឹមត្រូវ អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_1">%d</xliff:g> ដងទៀត</item>
+ <item quantity="one">លេខកូដសម្ងាត់ស៊ីមមិនត្រឹមត្រូវ អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_0">%d</xliff:g> ដងទៀត មុនពេលពេលដែលអ្នកត្រូវទាក់ទងទៅអ្នកផ្តល់សេវាកម្មរបស់អ្នកដើម្បីដោះសោឧបករណ៍របស់អ្នក។</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"ស៊ីមមិនអាចប្រើបាន។ ទាក់ទងក្រុមហ៊ុនបញ្ជូនរបស់អ្នក។"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"លេខកូដ PUK ស៊ីមមិនត្រឹមត្រូវ, អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់ មុនពេលស៊ីមក្លាយជាមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។"</item>
- <item quantity="other" msgid="5477305226026342036">"លេខកូដ PUK ស៊ីមមិនត្រឹមត្រូវ, អ្នកមាន <xliff:g id="NUMBER">%d</xliff:g> ការព្យាយាមដែលនៅសល់ មុនពេលស៊ីមក្លាយជាមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">លេខកូដ PUK ស៊ីមមិនត្រឹមត្រូវ អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_1">%d</xliff:g> ដងទៀត មុនពេលស៊ីមរបស់អ្នកមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។</item>
+ <item quantity="one">លេខកូដ PUK ស៊ីមមិនត្រឹមត្រូវ អ្នកនៅសល់ការព្យាយាម <xliff:g id="NUMBER_0">%d</xliff:g> ដងទៀត មុនពេលស៊ីមរបស់អ្នកមិនអាចប្រើបានជាអចិន្ត្រៃយ៍។</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"បានបរាជ័យក្នុងការប្រតិបត្តិលេខកូដ PIN ស៊ីម!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"បានបរាជ័យក្នុងការប្រតិបត្តិលេខកូដ PUK ស៊ីម!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"បានទទួលយកលេខកូដ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"គ្មានសេវា"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរប៊ូតុងវិធីសាស្ត្របញ្ចូល។"</string>
</resources>
diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml
index 02075f5..cfa1ac0 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ನಿಮ್ಮ ಅನ್ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%d</xliff:g> ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ನಿಮ್ಮ ಅನ್ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%d</xliff:g> ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಫೋನ್ ಅನ್ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ಸಿಮ್ ಪಿನ್ ಕೋಡ್ ತಪ್ಪಾಗಿದೆ, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಲು ನೀವು ಈ ಕೂಡಲೇ ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಬೇಕು."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ತಪ್ಪಾಗಿರುವ ಸಿಮ್ ಪಿನ್ ಕೋಡ್, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವ ಸಲುವಾಗಿ ನಿಮ್ಮ ವಾಹಕವನ್ನು ನೀವು ಸಂಪರ್ಕಿಸುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ."</item>
- <item quantity="other" msgid="2215723361575359486">"ತಪ್ಪಾಗಿರುವ ಸಿಮ್ ಪಿನ್ ಕೋಡ್, ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <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="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"ಸಿಮ್ ನಿಷ್ಪ್ರಯೋಜಕವಾಗಿದೆ. ನಿಮ್ಮ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ತಪ್ಪಾಗಿರುವ ಸಿಮ್ PUK ಕೋಡ್, ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನ ಬಾಕಿ ಉಳಿದಿದೆ."</item>
- <item quantity="other" msgid="5477305226026342036">"ತಪ್ಪಾಗಿರುವ ಸಿಮ್ PUK ಕೋಡ್, ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">ತಪ್ಪಾಗಿರುವ ಸಿಮ್ PUK ಕೋಡ್, ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ.</item>
+ <item quantity="other">ತಪ್ಪಾಗಿರುವ ಸಿಮ್ PUK ಕೋಡ್, ಸಿಮ್ ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಪ್ರಯೋಜಕವಾಗುವುದಕ್ಕೂ ಮೊದಲು ನಿಮ್ಮಲ್ಲಿ <xliff:g id="NUMBER_1">%d</xliff:g> ಪ್ರಯತ್ನಗಳು ಬಾಕಿ ಉಳಿದಿವೆ.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"ಸಿಮ್ ಪಿನ್ ಕಾರ್ಯಾಚರಣೆ ವಿಫಲಗೊಂಡಿದೆ!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"ಸಿಮ್ PUK ಕಾರ್ಯಾಚರಣೆ ವಿಫಲಗೊಂಡಿದೆ!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ಕೋಡ್ ಅಂಗೀಕೃತವಾಗಿದೆ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ಯಾವುದೇ ಸೇವೆಯಿಲ್ಲ."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ಇನ್ಪುಟ್ ವಿಧಾನ ಬದಲಿಸು ಬಟನ್."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 5cac9b8..1ef0c19 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 태블릿을 잠금해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%d</xliff:g>초 후에 다시 시도해 주세요."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN 코드가 잘못되었습니다. 이동통신사에 문의하여 기기를 잠금 해제해야 합니다."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN 코드가 잘못되었습니다. <xliff:g id="NUMBER">%d</xliff:g>회 이상 실패할 경우 이동통신사에 문의하여 기기를 잠금 해제해야 합니다."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN 코드가 잘못되었습니다. <xliff:g id="NUMBER">%d</xliff:g>번의 기회가 남았습니다."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN 코드가 잘못되었습니다. <xliff:g id="NUMBER_1">%d</xliff:g>번 더 시도할 수 있습니다.</item>
+ <item quantity="one">SIM PIN 코드가 잘못되었습니다. <xliff:g id="NUMBER_0">%d</xliff:g>번 더 실패하면 이동통신사에 문의하여 기기를 잠금 해제해야 합니다.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM을 사용할 수 없습니다. 이동통신사에 문의하세요."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK 코드가 잘못되었습니다. <xliff:g id="NUMBER">%d</xliff:g>회 이상 실패할 경우 SIM을 완전히 사용할 수 없습니다."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK 코드가 잘못되었습니다. <xliff:g id="NUMBER">%d</xliff:g>회 이상 실패할 경우 SIM을 완전히 사용할 수 없습니다."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK 코드가 잘못되었습니다. <xliff:g id="NUMBER_1">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다.</item>
+ <item quantity="one">SIM PUK 코드가 잘못되었습니다. <xliff:g id="NUMBER_0">%d</xliff:g>번 더 실패하면 SIM을 완전히 사용할 수 없게 됩니다.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN 작업이 실패했습니다."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK 작업이 실패했습니다."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"코드 승인 완료"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"서비스 불가"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml
index d04547c..430c19a 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Сиз бөгөттөн чыгаруу үлгүсүн <xliff:g id="NUMBER_0">%d</xliff:g> жолу туура эмес көрсөттүңүз. Дагы <xliff:g id="NUMBER_1">%d</xliff:g> ийгиликсиз аракеттен кийин, планшетиңизди эмейл эсебиңиз аркылуу бөгөттөн чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундадан кийин кайра аракеттениңиз."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Сиз бөгөттөн чыгаруу үлгүсүн <xliff:g id="NUMBER_0">%d</xliff:g> жолу туура эмес көрсөттүңүз. Дагы <xliff:g id="NUMBER_1">%d</xliff:g> ийгиликсиз аракеттен кийин, телефонуңузду эмейл эсебиңиз аркылуу бөгөттөн чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундадан кийин кайра аракеттениңиз."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM-карта PIN-коду туура эмес. Эми түзмөктү бөгөттөн чыгарыш үчүн операторуңузга кайрылышыңыз керек."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN-коду туура эмес, сиз түзмөктү бөгөттөн чыгарыш үчүн операторуңузга кайрылганга <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN-коду туура эмес, сизде <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN-коду туура эмес, сизде <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item>
+ <item quantity="one">SIM PIN-коду туура эмес, сизде <xliff:g id="NUMBER_0">%d</xliff:g> аракет калды. Болбосо, түзмөктүн кулпусун ачуу үчүн операторуңузга кайрылышыңыз керек.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-карта жараксыз. Операторуңузга кайрылыңыз."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK-коду туура эмес, SIM биротоло жарактан чыгаарына <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK-коду туура эмес, SIM биротоло жарактан чыгаарына <xliff:g id="NUMBER">%d</xliff:g> аракет калды."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK-коду туура эмес, SIM биротоло жарактан чыгаарынан мурун сизде <xliff:g id="NUMBER_1">%d</xliff:g> аракет калды.</item>
+ <item quantity="one">SIM PUK-коду туура эмес, SIM биротоло жарактан чыгаарынан мурун сизде <xliff:g id="NUMBER_0">%d</xliff:g> аракет калды.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM-картанын PIN-кодун ачуу кыйрады!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-картанын PUK-кодун ачуу кыйрады!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код кабыл алынды!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Байланыш жок."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Киргизүү ыкмасын которуу баскычы."</string>
</resources>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index af566d2..17c1c5b 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຜິດ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກແຕ້ມຜິດອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ເທື່ອ, ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກແທັບເລັດຂອງທ່ານ ດ້ວຍການເຂົ້າສູ່ລະບົບໂດຍໃຊ້ອີເມວຂອງທ່ານ.\n\n ກະລຸນາລອງໃໝ່ອີກຄັ້ງໃນອີກ <xliff:g id="NUMBER_2">%d</xliff:g> ວິນາທີ."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກຄວາມພະຍາຍາມອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ເທື່ອ ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກໂທລະສັບຂອງທ່ານດ້ວຍບັນຊີອີເມວ.\n\n ລອງໃໝ່ອີກຄັ້ງໃນ <xliff:g id="NUMBER_2">%d</xliff:g> ວິນາທີ."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງທ່ານຕ້ອງຕິດຕໍ່ຫາຜູ່ໃຫ້ບໍລິການ ເພື່ອປົດລັອກອຸປະກອນຂອງທ່ານ."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອກ່ອນທີ່ທ່ານຈະຕ້ອງຕິດຕໍ່ຫາຜູ່ໃຫ້ບໍລິການຂອງທ່ານ ເພື່ອປົດລັອກອຸປະກອນຂອງທ່ານ."</item>
- <item quantity="other" msgid="2215723361575359486">"ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">ລະຫັດ SIM PIN ບໍ່ຖືກຕ້ອງ, ທ່ານຍັງພະຍາຍາມໄດ້ອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ຄັ້ງ.</item>
+ <item quantity="one">ລະຫັດ PIN ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ທ່ານຈະຕ້ອງຕິດຕໍ່ຫາຜູ່ໃຫ້ບໍລິການຂອງທ່ານ ເພື່ອປົດລັອກອຸປະກອນຂອງທ່ານ.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM ໃຊ້ບໍ່ໄດ້ແລ້ວ. ກະລຸນາຕິດຕໍ່ຫາຜູ່ໃຫ້ບໍລິການຂອງທ່ານ."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ລະຫັດ PUK ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະໃຊ້ບໍ່ໄດ້ຢ່າງຖາວອນ."</item>
- <item quantity="other" msgid="5477305226026342036">"ລະຫັດ PUK ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະໃຊ້ບໍ່ໄດ້ຢ່າງຖາວອນ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">ລະຫັດ PUK ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_1">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະໃຊ້ບໍ່ໄດ້ຢ່າງຖາວອນ.</item>
+ <item quantity="one">ລະຫັດ PUK ຂອງ SIM ບໍ່ຖືກຕ້ອງ, ທ່ານສາມາດລອງໄດ້ອີກ <xliff:g id="NUMBER_0">%d</xliff:g> ເທື່ອກ່ອນທີ່ SIM ຂອງທ່ານຈະໃຊ້ບໍ່ໄດ້ຢ່າງຖາວອນ.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"PIN ຂອງ SIM ເຮັດວຽກລົ້ມເຫຼວ!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK ຂອງ SIM ເຮັດວຽກລົ້ມເຫຼວ!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ລະຫັດຖືກຕອບຮັບແລ້ວ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ບໍ່ມີບໍລິການ"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
</resources>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index 31c38cc..6d7dcc7 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami „Google“ prisijungimo duomenis.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%d</xliff:g> sek."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami „Google“ prisijungimo duomenis.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%d</xliff:g> sek."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Netinkamas SIM kortelės PIN kodas. Reikės susisiekti su operatoriumi, kad atrakintų įrenginį."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Netinkamas SIM kortelės PIN kodas. Jums liko <xliff:g id="NUMBER">%d</xliff:g> band. Paskui reikės susisiekti su operatoriumi, kad jis atrakintų įrenginį."</item>
- <item quantity="other" msgid="2215723361575359486">"Netinkamas SIM kortelės PIN kodas, liko <xliff:g id="NUMBER">%d</xliff:g> band."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Netinkamas SIM kortelės PIN kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymas.</item>
+ <item quantity="few">Netinkamas SIM kortelės PIN kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymai.</item>
+ <item quantity="many">Netinkamas SIM kortelės PIN kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymo.</item>
+ <item quantity="other">Netinkamas SIM kortelės PIN kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymų.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Nebegalima naudoti SIM kortelės. Susisiekite su operatoriumi."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER">%d</xliff:g> band. Paskui visiškai nebegalėsite naudoti SIM kortelės."</item>
- <item quantity="other" msgid="5477305226026342036">"Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER">%d</xliff:g> band. Paskui visiškai nebegalėsite naudoti SIM kortelės."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymas. Tada nebegalėsite naudotis SIM kortele.</item>
+ <item quantity="few">Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymai. Tada nebegalėsite naudotis SIM kortele.</item>
+ <item quantity="many">Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymo. Tada nebegalėsite naudotis SIM kortele.</item>
+ <item quantity="other">Netinkamas SIM kortelės PUK kodas. Liko <xliff:g id="NUMBER_1">%d</xliff:g> bandymų. Tada nebegalėsite naudotis SIM kortele.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Nepavyko atlikti SIM kortelės PIN kodo operacijos."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Nepavyko atlikti SIM kortelės PUK kodo operacijos."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodas priimtas."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nėra paslaugos."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
</resources>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index c13aef1..e1da889 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -95,17 +95,20 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem planšetdators būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundēm."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundēm."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Nepareizs SIM kartes PIN kods. Lai atbloķētu ierīci, sazinieties ar mobilo sakaru operatoru."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi. Kļūdas gadījumā būs jāsazinās ar mobilo sakaru operatoru, lai tas atbloķētu jūsu ierīci."</item>
- <item quantity="other" msgid="2215723361575359486">"Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi(-es)."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="zero">Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes.</item>
+ <item quantity="one">Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizi.</item>
+ <item quantity="other">Nepareizs SIM kartes PIN kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM karte nav izmantojama. Sazinieties ar mobilo sakaru operatoru."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Nepareizs SIM kartes PUK kods. Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi. Kļūdas gadījumā SIM karte kļūs neizmantojama."</item>
- <item quantity="other" msgid="5477305226026342036">"Nepareizs SIM kartes PUK kods. Varat mēģināt vēl <xliff:g id="NUMBER">%d</xliff:g> reizi(-es). Kļūdas gadījumā SIM karte kļūs neizmantojama."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="zero">Nepareizs SIM kartes PUK kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes. Pēdējā mēģinājuma kļūdas gadījumā SIM karte kļūs neizmantojama.</item>
+ <item quantity="one">Nepareizs SIM kartes PUK kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizi. Pēdējā mēģinājuma kļūdas gadījumā SIM karte kļūs neizmantojama.</item>
+ <item quantity="other">Nepareizs SIM kartes PUK kods. Varat mēģināt vēl <xliff:g id="NUMBER_1">%d</xliff:g> reizes. Pēdējā mēģinājuma kļūdas gadījumā SIM karte kļūs neizmantojama.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM kartes PIN koda ievadīšana neizdevās."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM kartes PUK koda ievadīšana neizdevās."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kods ir pieņemts!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nav pakalpojuma."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
</resources>
diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml
index 525cc29..717671b 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%d</xliff:g> пати. По <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни обиди, ќе побараат од вас да го отклучите таблетот со користење сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%d</xliff:g> пати. По <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни обиди, ќе побараат од вас да го отклучите телефонот со користење сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ПИН кодот за СИМ картичката е неточен. Контактирате со вашиот оператор да го отклучи уредот."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ПИН кодот за СИМ картичката е неточен. Ви преостанува уште <xliff:g id="NUMBER">%d</xliff:g> обид, а потоа ќе треба да контактирате со вашиот оператор да го отклучи уредот."</item>
- <item quantity="other" msgid="2215723361575359486">"ПИН кодот за СИМ картичката е неточен. Ви преостануваат уште <xliff:g id="NUMBER">%d</xliff:g> обиди."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <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="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"СМС картичката е неупотреблива. Контактирајте со вашиот оператор."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ПУК кодот за СИМ картичката е неточен. Ви преостанува уште <xliff:g id="NUMBER">%d</xliff:g> обид, а потоа СИМ картичката ќе стане трајно неупотреблива."</item>
- <item quantity="other" msgid="5477305226026342036">"ПУК кодот за СИМ картичката е неточен. Ви преостануваат уште <xliff:g id="NUMBER">%d</xliff:g> обиди, а потоа СИМ картичката ќе стане трајно неупотреблива."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <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="kg_password_pin_failed" msgid="6268288093558031564">"СИМ картичката не се отклучи со ПИН кодот!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"СИМ картичката не се отклучи со ПУК кодот!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кодот е прифатен!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Нема услуга."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Копче за префрање метод на внес."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml
index a91fe78..f39a6b7 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ടാബ്ലെറ്റ് അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"സിം പിൻ കോഡ് തെറ്റാണ്, നിങ്ങളുടെ ഉപകരണം അൺലോക്കുചെയ്യാൻ ഇപ്പോൾ നിങ്ങളുടെ കാരിയറുമായി ബന്ധപ്പെടണം."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"തെറ്റായ സിം പിൻ കോഡ്, നിങ്ങളുടെ ഉപകരണം അൺലോക്കുചെയ്യാൻ സേവനദാതാവുമായി ബന്ധപ്പെടുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമം കൂടി ബാക്കിയുണ്ട്."</item>
- <item quantity="other" msgid="2215723361575359486">"തെറ്റായ സിം പിൻ കോഡ്, നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ബാക്കിയുണ്ട്."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN കോഡ് തെറ്റാണ്, നിങ്ങൾക്ക് <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു.</item>
+ <item quantity="one">SIM PIN കോഡ് തെറ്റാണ്, നിങ്ങളുടെ ഉപകരണം അൺലോക്കുചെയ്യാൻ കാരിയറെ ബന്ധപ്പെടേണ്ടതിന് മുമ്പായി <xliff:g id="NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"സിം ഉപയോഗശൂന്യമാണ്. നിങ്ങളുടെ കാരിയറെ ബന്ധപ്പെടുക."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"തെറ്റായ സിം PUK കോഡ്, സിം ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമം കൂടി ബാക്കിയുണ്ട്."</item>
- <item quantity="other" msgid="5477305226026342036">"തെറ്റായ സിം PUK കോഡ്, സിം ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ബാക്കിയുണ്ട്."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK കോഡ് തെറ്റാണ്, SIM ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER_1">%d</xliff:g> ശ്രമങ്ങൾ കൂടി ശേഷിക്കുന്നു.</item>
+ <item quantity="one">SIM PUK കോഡ് തെറ്റാണ്, SIM ശാശ്വതമായി ഉപയോഗശൂന്യമാകുന്നതിന് മുമ്പായി നിങ്ങൾക്ക് <xliff:g id="NUMBER_0">%d</xliff:g> ശ്രമം കൂടി ശേഷിക്കുന്നു.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"സിം പിൻ പ്രവർത്തനം പരാജയപ്പെട്ടു!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"സിം PUK പ്രവർത്തനം പരാജയപ്പെട്ടു!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"കോഡ് അംഗികരിച്ചു!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"സേവനമൊന്നുമില്ല."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ടൈപ്പുചെയ്യൽ രീതി ബട്ടൺ മാറുക."</string>
</resources>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index 0182a6c..2f24901 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Та тайлах хээг <xliff:g id="NUMBER_0">%d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд имэйл акаунт шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Та тайлах хээг <xliff:g id="NUMBER_0">%d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл акаунтаа ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> секундын дараа дахин оролдоно уу."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"СИМ ПИН код буруу, та төхөөрөмжийн түгжээг тайлахын тулд оператор компанитай холбоо барих шаардлагатай."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"СИМ ПИН код буруу байна, танд мобайл оператор компанитай холбогдохгүйгээр төхөөрөмжийн түгжээг тайлахад <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдсэн байна."</item>
- <item quantity="other" msgid="2215723361575359486">"СИМ ПИН код буруу байна, танд <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдлээ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">СИМ-ны ПИН код буруу байна. Та <xliff:g id="NUMBER_1">%d</xliff:g> удаа оролдлого хийх боломжтой байна.</item>
+ <item quantity="one">СИМ-ны ПИН код буруу байна. Танд мобайл оператортойгоо холбогдохгүйгээр төхөөрөмжийн түгжээг тайлахад <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого хийх боломж үлдсэн байна.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"СИМ ашиглах боломжгүй. Өөрийн оператор компанитай холбоо барина уу."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"СИМ ПҮК код буруу, таны СИМ бүрмөсөн ашиглалтгүй болохоос өмнө <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдлээ."</item>
- <item quantity="other" msgid="5477305226026342036">"СИМ ПҮК код буруу, таны СИМ бүрмөсөн ашиглалтгүй болохоос өмнө <xliff:g id="NUMBER">%d</xliff:g> оролдлого хийх боломж үлдлээ."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">]СИМ-ны PUK код буруу байна. Таны СИМ хаагдах хүртэл төхөөрөмжийн түгжээг тайлахад <xliff:g id="NUMBER_1">%d</xliff:g> .оролдлого хийх боломж үлдсэн байна.</item>
+ <item quantity="one">СИМ-ны PUK код буруу байна. Таны СИМ хаагдах хүртэл төхөөрөмжийн түгжээг тайлахад <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого хийх боломж үлдсэн байна.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"СИМ ПИН ажиллуулах амжилтгүй боллоо!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"СИМ ПҮК ажиллуулах амжилтгүй боллоо!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код зөвшөөрөгдлөө!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Үйлчилгээ байхгүй."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</string>
</resources>
diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml
index fc30fc8..a86bf60 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपण आपला अनलॉक नमुना <xliff:g id="NUMBER_0">%d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%d</xliff:g> अयशस्वी प्रयत्नांनंतर, आपल्याला ईमेल खाते वापरून आपला टॅब्लेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपण आपला अनलॉक नमुना <xliff:g id="NUMBER_0">%d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%d</xliff:g> अयशस्वी प्रयत्नांनंतर, आपल्याला ईमेल खाते वापरून आपला फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"सिम पिन कोड चुकीचा आहे आपण आता आपले डिव्हाइस अनलॉक करण्यासाठी आपल्या वाहकाशी संपर्क साधावा."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"सिम पिन कोड चुकीचा आहे, आपण आपले डिव्हाइस अनलॉक करण्यासाठी आपल्या वाहकाशी संपर्क साधण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहेत."</item>
- <item quantity="other" msgid="2215723361575359486">"सिम पिन कोड चुकीचा आहे, आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहेत."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <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="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"सिम निरुपयोगी आहे. आपल्या वाहकाशी संपर्क साधा."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"सिम PUK कोड चुकीचा आहे, सिम कायमचे निरूपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहे."</item>
- <item quantity="other" msgid="5477305226026342036">"सिम PUK कोड चुकीचा आहे, सिम कायमचे निरूपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> प्रयत्न उर्वरित आहेत."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">सिम PUK कोड चुकीचा आहे, सिम कायमचे निरूपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न उर्वरित आहे.</item>
+ <item quantity="other">सिम PUK कोड चुकीचा आहे, सिम कायमचे निरूपयोगी होण्यापूर्वी आपल्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न उर्वरित आहेत.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"सिम पिन कार्य अयशस्वी झाले!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"सिम PUK कार्य अयशस्वी झाले!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकारला!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"सेवा नाही."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धत स्विच करा बटण."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index e1907da..3d4dee4 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Anda telah tersilap melukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci tablet anda menggunakan log masuk Google anda.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Kod PIN SIM tidak betul, jadi anda harus menghubungi pembawa anda untuk membuka kunci peranti."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Kod PIN SIM tidak betul. Anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi sebelum anda harus menghubungi pembawa anda untuk membuka kunci peranti."</item>
- <item quantity="other" msgid="2215723361575359486">"Kod PIN SIM tidak betul, anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Kod PIN SIM salah, anda ada <xliff:g id="NUMBER_1">%d</xliff:g> cubaan lagi.</item>
+ <item quantity="one">Kod PIN SIM tidak betul. Anda ada <xliff:g id="NUMBER_0">%d</xliff:g> cubaan lagi sebelum anda harus menghubungi pembawa anda untuk membuka kunci peranti.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM tidak boleh digunakan. Hubungi pembawa anda."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Kod PUK SIM tidak betul, anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi sebelum SIM tidak boleh digunakan secara kekal."</item>
- <item quantity="other" msgid="5477305226026342036">"Kod PUK SIM tidak betul, anda mempunyai <xliff:g id="NUMBER">%d</xliff:g> percubaan lagi sebelum SIM tidak boleh digunakan secara kekal."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Kod PUK SIM tidak betul, anda ada <xliff:g id="NUMBER_1">%d</xliff:g> cubaan lagi sebelum SIM tidak boleh digunakan secara kekal.</item>
+ <item quantity="one">Kod PUK SIM tidak betul, anda ada <xliff:g id="NUMBER_0">%d</xliff:g> cubaan lagi sebelum SIM tidak boleh digunakan secara kekal.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operasi PIN SIM gagal!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operasi PUK SIM gagal!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Diterima!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Tiada perkhidmatan."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
</resources>
diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml
index 53dcdb0..4432ceb 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"သင် ပုံဖော်၍သော့ဖွင့်ခြင်းကို <xliff:g id="NUMBER_0">%d</xliff:g> အကြိမ် မှန်ကန်စွာ မပြုလုပ်နိုင်ပါ။ နောက်ထပ် <xliff:g id="NUMBER_1">%d</xliff:g> အကြိမ် မမှန်ကန်ပါက သင့်တက်ဘလက်အား အီးမေးလ်အသုံးပြု၍ သော့ဖွင့်ရန် တောင်းဆိုပါလိမ့်မည်။ \n\n <xliff:g id="NUMBER_2">%d</xliff:g> စက္ကန့်အကြာတွင် ပြန်လည် ကြိုးစားပါ"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"သင် ပုံဖော်၍သော့ဖွင့်ခြင်းကို <xliff:g id="NUMBER_0">%d</xliff:g> အကြိမ် မှန်ကန်စွာ မပြုလုပ်နိုင်ပါ။ နောက်ထပ် <xliff:g id="NUMBER_1">%d</xliff:g> အကြိမ် မမှန်ကန်ပါက သင့်ဖုန်းအား အီးမေးလ်အသုံးပြု၍ သော့ဖွင့်ရန် တောင်းဆိုပါလိမ့်မည်။ \n\n <xliff:g id="NUMBER_2">%d</xliff:g> စက္ကန့်အကြာတွင် ပြန်လည် ကြိုးစားပါ"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"ဆင်းကဒ် လျှို့ဝှက် အမှတ် မှားယွင်းပါသည်, ဖုန်းလိုင်းဌာနကို ဆက်သွယ်ရမည် ဖြစ်ပါတယ်"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"ဆင်းမ်ကဒ်၏ လျှို့ဝှက်နံပါတ် မှားနေပါသည်၊ သင်၏ စက်ပစ္စည်းကို သော့ဖွင့်ရန် ဖုန်းလိုင်းဌာနသို့ မဆက်သွယ်မီ သင့်တွင် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။"</item>
- <item quantity="other" msgid="2215723361575359486">"ဆင်းမ်ကဒ်၏ လျှို့ဝှက်နံပါတ် မှားနေပါသည်၊ သင့်တွင် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">ဆင်းမ်ကဒ်၏ ပင်နံပါတ် မှားနေပါသည်၊ သင့်တွင်<xliff:g id="NUMBER_1">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item>
+ <item quantity="one">ဆင်းမ်ကဒ်၏ ပင်နံပါတ် မှားနေပါသည်၊ သင့်ကိရိယာကို ဖွင့်ရန် မိုဘိုင်းဖုန်းဆက်သွယ်ရေးဝန်ဆောင်မှုဌာနသို့ မဆက်သွယ်မီ သင့်တွင် <xliff:g id="NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့် ကျန်ပါသေးသည်။</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"ဆင်းမ်ကဒ်သုံးလို့မရတော့ပါ. ဖုန်းလိုင်းဌာနကို ဆက်သွယ်ပါ"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"ဆင်းမ်ကဒ်၏ ပင်နံပါတ်ပြန်ဖွင့်သည့်ကုဒ်နံပါတ် မှားနေပါသည်။ နောက်ထပ် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစား၍ မအောင်မြင်ံပါက ဆင်းမ်ကဒ် ဆက်မသုံးနိုင်အောင် ပျက်စီးသွားမည် ဖြစ်ပါသည်"</item>
- <item quantity="other" msgid="5477305226026342036">"ဆင်းမ်ကဒ်၏ ပင်နံပါတ်ပြန်ဖွင့်သည့် ကုဒ်နံပါတ် မှားနေပါသည်။ နောက်ထပ် <xliff:g id="NUMBER">%d</xliff:g> ခါ ကြိုးစား၍ မအောင်မြင်ံပါက ဆင်းမ်ကဒ် ဆက်မသုံးနိုင်အောင် ပျက်စီးသွားမည် ဖြစ်ပါသည်"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">ဆင်းမ်ကဒ်၏ ပင်နံပါတ်ပြန်ဖွင့်သည့် ကုဒ် (PUK) မမှန်ပါ၊ ဆင်းမ်ကဒ်သည် ဆက်လက်အသုံးမပြုနိုင်အောင် မဖြစ်လာခင် သင့်တွင် <xliff:g id="NUMBER_1">%d</xliff:g>ခါ ကြိုးစားခွင့်များကျန်ပါသေးသည်။</item>
+ <item quantity="one">ဆင်းမ်ကဒ်၏ ပင်နံပါတ်ပြန်ဖွင့်သည့် ကုဒ် (PUK) မမှန်ပါ၊ ဆင်းမ်ကဒ်သည် ဆက်လက်အသုံးမပြုနိုင်အောင် မဖြစ်လာခင် သင့်တွင် <xliff:g id="NUMBER_0">%d</xliff:g> ခါ ကြိုးစားခွင့်ကျန်ပါသေးသည်။</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"ဆင်းမ်ကဒ် ပင် လုပ်ဆောင်မှု မအောင်မြင်ပါ"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် လုပ်ဆောင်မှု မအောင်မြင်ပါ"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ကုဒ်နံပါတ်ကို လက်ခံလိုက်ပါသည်"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ဆားဗစ် မရှိပါ"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ထည့်သွင်းခြင်းခလုတ်အား ပြောင်းခြင်း"</string>
</resources>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index c84f74e..efc25cf 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, blir du bedt om å låse opp nettbrettet via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%d</xliff:g> gale forsøk, blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Feil PIN-kode for SIM-kortet. Du må nå kontakte operatøren din for å låse opp enheten."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Feil PIN-kode for SIM-kortet. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen før du må kontakte operatøren din for å låse opp enheten."</item>
- <item quantity="other" msgid="2215723361575359486">"Feil PIN-kode for SIM-kortet. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Feil PIN-kode for SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøk igjen.</item>
+ <item quantity="one">Feil PIN-kode for SIM-kortet. Du har <xliff:g id="NUMBER_0">%d</xliff:g> forsøk igjen før du må kontakte operatøren din for å låse opp enheten.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-kortet er ubrukelig. Kontakt operatøren din."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Feil PUK-kode for SIM-kortet. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig."</item>
- <item quantity="other" msgid="5477305226026342036">"Feil PUK-kode for SIM-kortet. Du har <xliff:g id="NUMBER">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Feil PUK-kode for SIM-kortet. Du har <xliff:g id="NUMBER_1">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig.</item>
+ <item quantity="one">Feil PUK-kode for SIM-kortet. Du har <xliff:g id="NUMBER_0">%d</xliff:g> forsøk igjen før SIM-kortet blir permanent ubrukelig.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"PIN-koden for SIM-kortet ble avvist."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-koden for SIM-kortet ble avvist."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden er godkjent."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjeneste."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index d9d0e2e..7f6843a 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"तपाईंले गलत तरिकाले आफ्नो अनलक ढाँचा <xliff:g id="NUMBER_0">%d</xliff:g> पटक कोर्नुभयो। <xliff:g id="NUMBER_1">%d</xliff:g> विफल प्रयत्नहरू पछि, तपाईंलाई आफ्नो ट्याब्लेट इमेल खाता प्रयोग गरेर अनलक गर्न सोधिने छ।\n\n फेरि प्रयास गर्नुहोस् <xliff:g id="NUMBER_2">%d</xliff:g> सेकेन्डहरूमा।"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"तपाईँले आफ्नो अनलक ढाँचा गलत रूपमा <xliff:g id="NUMBER_0">%d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN कोड गलत छ। अब तपाईंले अाफ्नो उपकरण खोल्नलाई तपाईंको वाहकसँग सम्पर्क गर्नै पर्दर।"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN कोड गलत छ, तपाईंले अाफ्नो उपकरण खोल्नलाई तपाईंको वाहकसँग सम्पर्क गर्नै पर्दछ यस अघि तपाईंसँग <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयास छ।"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN कोड गलत छ, तपाईंसँग <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयासहरू छन्।"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other"> गलत SIM PIN कोड, तपाईं सँग <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+ <item quantity="one">SIM PIN कोड गलत छ, तपाईंले अाफ्नो यन्त्र खोल्नलाई तपाईंको वाहकसँग सम्पर्क गर्नै पर्न अघि तपाईंसँग <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM प्रयोग बिहिन छ। तपाईंको वाहकलाई सम्पर्क गर्नुहोस्।"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK कोड गलत छ, तपाईंसँग SIM स्थायी रूपमा काम नलाग्ने हुनु अघि <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयास छ।"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK कोड गलत छ, तपाईंसँग SIM स्थायी रूपमा काम नलाग्ने हुनु अघि <xliff:g id="NUMBER">%d</xliff:g> बाँकी प्रयासहरू छन्।"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK कोड गलत छ, तपाईंसँग SIM स्थायी रूपमा काम नलाग्ने हुनु अघि <xliff:g id="NUMBER_1">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+ <item quantity="one">SIM PUK कोड गलत छ, तपाईंसँग SIM स्थायी रूपमा काम नलाग्ने हुनु अघि <xliff:g id="NUMBER_0">%d</xliff:g> पटक प्रयास बाँकी छ।</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN राख्ने कार्य बिफल भयो!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK राख्ने कार्य बिफल भयो!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकृत!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"कुनै सेवा छैन।"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट विधि बटन स्विच गर्नुहोस्।"</string>
</resources>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index 2011b7c..3a8d91c 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"U heeft uw ontgrendelingspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen wordt u gevraagd uw tablet te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%d</xliff:g> seconden opnieuw."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"U heeft uw ontgrendelingspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%d</xliff:g> mislukte pogingen wordt u gevraagd uw telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%d</xliff:g> seconden opnieuw."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Onjuiste pincode voor simkaart. U moet nu contact opnemen met uw provider om uw apparaat te ontgrendelen."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Onjuiste pincode voor simkaart. U heeft nog <xliff:g id="NUMBER">%d</xliff:g> poging over voordat u contact met uw provider moet opnemen om uw apparaat te ontgrendelen."</item>
- <item quantity="other" msgid="2215723361575359486">"Onjuiste pincode voor simkaart. U heeft nog <xliff:g id="NUMBER">%d</xliff:g> pogingen over."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Onjuiste pincode voor simkaart. U heeft nog <xliff:g id="NUMBER_1">%d</xliff:g> pogingen over.</item>
+ <item quantity="one">Onjuiste pincode voor simkaart. U heeft nog <xliff:g id="NUMBER_0">%d</xliff:g> poging over voordat u contact met uw provider moet opnemen om uw apparaat te ontgrendelen.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Simkaart is onbruikbaar. Neem contact op met uw provider."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Onjuiste pukcode voor simkaart. U heeft nog <xliff:g id="NUMBER">%d</xliff:g> poging over voordat de simkaart definitief onbruikbaar wordt."</item>
- <item quantity="other" msgid="5477305226026342036">"Onjuiste pukcode voor simkaart. U heeft nog <xliff:g id="NUMBER">%d</xliff:g> pogingen over voordat de simkaart definitief onbruikbaar wordt."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Onjuiste pukcode voor simkaart. U heeft nog <xliff:g id="NUMBER_1">%d</xliff:g> pogingen over voordat de simkaart definitief onbruikbaar wordt.</item>
+ <item quantity="one">Onjuiste pukcode voor simkaart. U heeft nog <xliff:g id="NUMBER_0">%d</xliff:g> poging over voordat de simkaart definitief onbruikbaar wordt.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Bewerking met pincode voor simkaart mislukt."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Bewerking met pukcode voor simkaart is mislukt."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code geaccepteerd."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen service"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
</resources>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index 38b4676..b47b76e 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie tabletu przy użyciu danych logowania na konto Google.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Nieprawidłowy kod PIN karty SIM. Musisz teraz skontaktować się z operatorem, by odblokował Twoje urządzenie."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> próbę, zanim będziesz musiał skontaktować się z operatorem, by odblokował Twoje urządzenie."</item>
- <item quantity="other" msgid="2215723361575359486">"Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> prób(y)."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="few">Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby.</item>
+ <item quantity="many">Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> prób.</item>
+ <item quantity="other">Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby.</item>
+ <item quantity="one">Nieprawidłowy kod PIN karty SIM. Masz jeszcze <xliff:g id="NUMBER_0">%d</xliff:g> próbę, zanim będziesz musiał skontaktować się z operatorem, by odblokować swoje urządzenie.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Karta SIM została trwale zablokowana. Skontaktuj się z operatorem."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> próbę, zanim karta SIM zostanie trwale zablokowana."</item>
- <item quantity="other" msgid="5477305226026342036">"Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER">%d</xliff:g> prób(y), zanim karta SIM zostanie trwale zablokowana."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="few">Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie trwale zablokowana.</item>
+ <item quantity="many">Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> prób, zanim karta SIM zostanie trwale zablokowana.</item>
+ <item quantity="other">Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> próby, zanim karta SIM zostanie trwale zablokowana.</item>
+ <item quantity="one">Nieprawidłowy kod PUK karty SIM. Masz jeszcze <xliff:g id="NUMBER_0">%d</xliff:g> próbę, zanim karta SIM zostanie trwale zablokowana.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operacja z kodem PIN karty SIM nie udała się."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operacja z kodem PUK karty SIM nie udała się."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod został zaakceptowany."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Brak usługi."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
</resources>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index e9ab8de..9068898 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o tablet através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativa antes de necessitar de contactar o seu operador para desbloquear o dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativas."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
+ <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de necessitar de contactar o seu operador para desbloquear o dispositivo.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Cartão SIM inutilizável. Contacte o seu operador."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável."</item>
- <item quantity="other" msgid="5477305226026342036">"Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
+ <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Falha ao introduzir o PIN do cartão SIM!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Falha ao introduzir o PUK do cartão SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceite!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
</resources>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index 0e2cba7..690b693 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Código PIN do SIM incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g>. Caso o código correto não seja digitado, será necessário entrar em contato com a operadora para desbloquear o dispositivo."</item>
- <item quantity="other" msgid="2215723361575359486">"Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+ <item quantity="other">Código PIN do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"O SIM está inutilizável. Entre em contato com a operadora."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g> Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável."</item>
- <item quantity="other" msgid="5477305226026342036">"Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER">%d</xliff:g>. Caso o código correto não seja digitado, o SIM se tornará permanentemente inutilizável."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM não poderá mais ser usado.</item>
+ <item quantity="other">Código PUK do SIM incorreto. Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o SIM não poderá mais ser usado.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Falha na operação de PIN do SIM."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Falha na operação de PUK do SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceito."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index e36a37d..1e6fc00 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -95,17 +95,20 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul unui cont de e-mail.\n\n Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul unui cont de e-mail.\n\n Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Codul PIN pentru cardul SIM este incorect. Contactați operatorul pentru a vă debloca dispozitivul."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Codul PIN pentru cardul SIM este incorect. V-a mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercare, după care va trebui să contactați operatorul pentru a vă debloca dispozitivul."</item>
- <item quantity="other" msgid="2215723361575359486">"Codul PIN pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercări."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="few">Codul PIN pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări.</item>
+ <item quantity="other">Codul PIN pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> de încercări.</item>
+ <item quantity="one">Codul PIN pentru cardul SIM este incorect. V-a mai rămas <xliff:g id="NUMBER_0">%d</xliff:g> încercare, după care va trebui să contactați operatorul pentru a vă debloca dispozitivul.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Cardul SIM nu poate fi utilizat. Contactați operatorul."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Codul PUK pentru cardul SIM este incorect. V-a mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercare până când cardul SIM va deveni inutilizabil definitiv."</item>
- <item quantity="other" msgid="5477305226026342036">"Codul PUK pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER">%d</xliff:g> încercări până când cardul SIM va deveni inutilizabil definitiv."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="few">Codul PUK pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> încercări până când cardul SIM va deveni inutilizabil definitiv.</item>
+ <item quantity="other">Codul PUK pentru cardul SIM este incorect. V-au mai rămas <xliff:g id="NUMBER_1">%d</xliff:g> de încercări până când cardul SIM va deveni inutilizabil definitiv.</item>
+ <item quantity="one">Codul PUK pentru cardul SIM este incorect. V-a mai rămas <xliff:g id="NUMBER_0">%d</xliff:g> încercare până când cardul SIM va deveni inutilizabil definitiv.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Deblocarea cu ajutorul codului PIN pentru cardul SIM nu a reușit!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Deblocarea cu ajutorul codului PUK pentru cardul SIM nu a reușit!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Cod acceptat!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Fără serviciu."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 9ea14ff..48fd4f6 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки планшетного ПК потребуется войти в аккаунт Google.\n\nПовтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Вы <xliff:g id="NUMBER_0">%d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google.\n\nПовтор через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Неверный PIN-код. Обратитесь к оператору связи, чтобы разблокировать SIM-карту."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Неверный PIN-код. Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>. После этого SIM-карта будет заблокирована и вам придется обратиться к оператору связи."</item>
- <item quantity="other" msgid="2215723361575359486">"Неверный PIN-код. Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Неверный PIN-код. Осталась <xliff:g id="NUMBER_1">%d</xliff:g> попытка. После этого SIM-карта будет заблокирована и вам придется обратиться к оператору связи.</item>
+ <item quantity="few">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована и вам придется обратиться к оператору связи.</item>
+ <item quantity="many">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована и вам придется обратиться к оператору связи.</item>
+ <item quantity="other">Неверный PIN-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована и вам придется обратиться к оператору связи.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-карта заблокирована навсегда. Обратитесь к оператору связи."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Неверный PUK-код. Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>. После этого SIM-карта будет заблокирована навсегда."</item>
- <item quantity="other" msgid="5477305226026342036">"Неверный PUK-код. Осталось попыток: <xliff:g id="NUMBER">%d</xliff:g>. После этого SIM-карта будет заблокирована навсегда."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Неверный PUK-код. Осталась <xliff:g id="NUMBER_1">%d</xliff:g> попытка. После этого SIM-карта будет заблокирована навсегда.</item>
+ <item quantity="few">Неверный PUK-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попытки. После этого SIM-карта будет заблокирована навсегда.</item>
+ <item quantity="many">Неверный PUK-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована навсегда.</item>
+ <item quantity="other">Неверный PUK-код. Осталось <xliff:g id="NUMBER_1">%d</xliff:g> попыток. После этого SIM-карта будет заблокирована навсегда.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Не удалось разблокировать SIM-карту"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Не удалось разблокировать SIM-карту"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код принят"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Нет сигнала."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
</resources>
diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml
index af10fc9..740b0ea 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ඔබ අගුළු ඇරිමේ රටාව <xliff:g id="NUMBER_0">%d</xliff:g> වතාවක් වැරදියට ඇඳ ඇත. තවත් අසාර්ථක උත්සාහ <xliff:g id="NUMBER_1">%d</xliff:g> කින් පසුව, ඊ-තැපැල් ගිණුම භාවිතා කරමින් ඔබගේ ටැබ්ලටයේ අගුළු ඇරීමට ඔබට පවසනු ඇත.\n\n නැවත තත්පර <xliff:g id="NUMBER_2">%d</xliff:g> කින් උත්සාහ කරන්න."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"වැරදී SIM PIN කේතයකි, ඔබගේ දුරකතනයේ අඟුල හැරීමට ඔබගේ වාහකයා ඔබ දැන් සම්බන්ධ කරගත යුතුය."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"වැරදී SIM PIN කේතයකි, ඔබගේ දුරකතනයේ අඟුල හැරීමට ඔබගේ වාහකයා සම්බන්ධ කරගැනීමට පෙර ඔබ සතුව තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ඉතිරිව ඇත."</item>
- <item quantity="other" msgid="2215723361575359486">"වැරදී SIM PIN කේතයකි, ඔබ සතුව තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ඉතිරිව ඇත."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">වැරදි SIM PIN කේතයකි, ඔබට උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ක් ඉතිරිව ඇත.</item>
+ <item quantity="other">වැරදි SIM PIN කේතයකි, ඔබට උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ක් ඉතිරිව ඇත.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM කාඩ් පත භාවිතා කළ නොහැක. ඔබගේ වාහකය සම්බන්ධ කරගන්න."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"වැරදී SIM PUK කේතයකි, SIM කාඩ් පත සදාකාලිකව භාවිතා කළ නොහැකි තත්ත්වයට පත්වීමට ඔබට තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ඉතිරිව ඇත."</item>
- <item quantity="other" msgid="5477305226026342036">"වැරදී SIM PUK කේතයකි, SIM කාඩ් පත සදාකාලිකව භාවිතා කළ නොහැකි තත්ත්වයට පත්වීමට ඔබට තවත් උත්සාහයන් <xliff:g id="NUMBER">%d</xliff:g> ඉතිරිව ඇත."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">වැරදී SIM PUK කේතයකි, SIM කාඩ් පත ස්ථිරවම පාවිච්චි කළ නොහැකි ලෙසට පත්වීමට පෙර ඔබට තවත් උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ඉතිරිව ඇත.</item>
+ <item quantity="other">වැරදී SIM PUK කේතයකි, SIM කාඩ් පත ස්ථිරවම පාවිච්චි කළ නොහැකි ලෙසට පත්වීමට පෙර ඔබට තවත් උත්සාහයන් <xliff:g id="NUMBER_1">%d</xliff:g> ඉතිරිව ඇත.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN ක්රියාවලිය අපොහොසත් විය!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ක්රියාවලිය අපොහොසත් විය!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"කේතය පිළිගැණුනි!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"සේවාව නැත."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ආදාන ක්රමය මාරු කිරීමේ බොත්තම."</string>
</resources>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index f1b92ac..2fbe838 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších <xliff:g id="NUMBER_1">%d</xliff:g> neúspešných pokusoch sa zobrazí výzva na odomknutie tabletu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Nesprávny kód PIN karty SIM. Teraz musíte kontaktovať svojho operátora, aby vám odomkol zariadenie."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Nesprávny kód PIN karty SIM. Zostáva vám <xliff:g id="NUMBER">%d</xliff:g> pokus, inak budete musieť kontaktovať svojho operátora, aby vám odomkol zariadenie."</item>
- <item quantity="other" msgid="2215723361575359486">"Nesprávny kód PIN karty SIM. Počet zostávajúcich pokusov: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="few">Nesprávny kód PIN SIM karty. Zostávajú vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusy.</item>
+ <item quantity="many">Nesprávny kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusu.</item>
+ <item quantity="other">Nesprávny kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusov.</item>
+ <item quantity="one">Nesprávny kód PIN SIM karty. Zostáva vám <xliff:g id="NUMBER_0">%d</xliff:g> pokus, potom budete musieť kontaktovať svojho operátora, aby vám odomkol zariadenie.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Karta SIM je nepoužiteľná. Kontaktujte svojho operátora."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Nesprávny kód PUK karty SIM. Zostáva vám <xliff:g id="NUMBER">%d</xliff:g> pokus, inak sa vaša karta SIM natrvalo zablokuje."</item>
- <item quantity="other" msgid="5477305226026342036">"Nesprávny kód PUK karty SIM. Počet zostávajúcich pokusov pred trvalým zablokovaním karty SIM: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="few">Nesprávny kód PUK SIM karty. Zostávajú vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusy, potom sa SIM karta natrvalo zablokuje.</item>
+ <item quantity="many">Nesprávny kód PUK SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusu, potom sa SIM karta natrvalo zablokuje.</item>
+ <item quantity="other">Nesprávny kód PUK SIM karty. Zostáva vám <xliff:g id="NUMBER_1">%d</xliff:g> pokusov, potom sa SIM karta natrvalo zablokuje.</item>
+ <item quantity="one">Nesprávny kód PUK SIM karty. Zostáva vám <xliff:g id="NUMBER_0">%d</xliff:g> pokus, potom sa SIM karta natrvalo zablokuje.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Operácia kódu PIN karty SIM zlyhala!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operácia kódu PUK karty SIM zlyhala!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód bol prijatý!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Žiadny signál"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
</resources>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index d67c212..a79d99a 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da tablični računalnik odklenete z e-poštnim računom.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Napačna koda PIN kartice SIM. Zdaj se boste morali za odklenitev naprave obrniti na operaterja."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER">%d</xliff:g> poskus. Potem se boste morali za odklenitev naprave obrniti na operaterja."</item>
- <item quantity="other" msgid="2215723361575359486">"Napačna koda PIN kartice SIM. Poskusite lahko še <xliff:g id="NUMBER">%d</xliff:g>-krat."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskus.</item>
+ <item quantity="two">Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusa.</item>
+ <item quantity="few">Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskuse.</item>
+ <item quantity="other">Napačna koda PIN kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusov.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Kartica SIM ni več uporabna. Obrnite se na operaterja."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Napačna koda PUK kartice SIM. Na voljo imate še <xliff:g id="NUMBER">%d</xliff:g> poskus. Potem bo kartica SIM postala trajno neuporabna."</item>
- <item quantity="other" msgid="5477305226026342036">"Napačna koda PUK kartice SIM. Poskusite lahko še <xliff:g id="NUMBER">%d</xliff:g>-krat. Potem bo kartica SIM postala trajno neuporabna."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Napačna koda PUK kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskus. Potem bo kartica SIM postala trajno neuporabna.</item>
+ <item quantity="two">Napačna koda PUK kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusa. Potem bo kartica SIM postala trajno neuporabna.</item>
+ <item quantity="few">Napačna koda PUK kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskuse. Potem bo kartica SIM postala trajno neuporabna.</item>
+ <item quantity="other">Napačna koda PUK kartice SIM. Na voljo imate še <xliff:g id="NUMBER_1">%d</xliff:g> poskusov. Potem bo kartica SIM postala trajno neuporabna.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Postopek za odklepanje s kodo PIN kartice SIM ni uspel."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Postopek za odklepanje s kodo PUK kartice SIM ni uspel."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koda je sprejeta."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ni storitve."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
</resources>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index 8438315..b7c439b 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -95,17 +95,20 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање неисправно <xliff:g id="NUMBER_0">%d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПокушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Нетачан SIM PIN кôд. Сада морате да контактирате мобилног оператера да бисте откључали уређај."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER">%d</xliff:g> покушај, а онда морате да контактирате мобилног оператера да бисте откључали уређај."</item>
- <item quantity="other" msgid="2215723361575359486">"Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER">%d</xliff:g> покушаја."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај.</item>
+ <item quantity="few">Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја.</item>
+ <item quantity="other">Нетачан SIM PIN кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM картица је неупотребљива. Контактирајте мобилног оператера."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Нетачан SIM PUK кôд. Имате још <xliff:g id="NUMBER">%d</xliff:g> покушај пре него што SIM картица постане трајно неупотребљива."</item>
- <item quantity="other" msgid="5477305226026342036">"Нетачан SIM PUK кôд. Имате још <xliff:g id="NUMBER">%d</xliff:g> покушаја пре него што SIM картица постане трајно неупотребљива."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Нетачан SIM PUK кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушај пре него што SIM картица постане трајно неупотребљива.</item>
+ <item quantity="few">Нетачан SIM PUK кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја пре него што SIM картица постане трајно неупотребљива.</item>
+ <item quantity="other">Нетачан SIM PUK кôд. Имате још <xliff:g id="NUMBER_1">%d</xliff:g> покушаја пре него што SIM картица постане трајно неупотребљива.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Радња са SIM PIN кодом није успела!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Радња са SIM PUK кодом није успела!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кôд је прихваћен!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Офлајн сте."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</string>
</resources>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index d55c72f..75adc2c 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp surfplattan med ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%d</xliff:g> sekunder."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Du angav fel pinkod för SIM-kortet och måste nu kontakta operatören för att låsa upp enheten."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Du angav fel pinkod för SIM-kortet. <xliff:g id="NUMBER">%d</xliff:g> försök återstår innan du måste kontakta operatören för att låsa upp enheten."</item>
- <item quantity="other" msgid="2215723361575359486">"Du angav fel pinkod för SIM-kortet. <xliff:g id="NUMBER">%d</xliff:g> försök återstår."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Du angav fel pinkod för SIM-kortet. <xliff:g id="NUMBER_1">%d</xliff:g> försök återstår.</item>
+ <item quantity="one">Du angav fel pinkod för SIM-kortet. <xliff:g id="NUMBER_0">%d</xliff:g> försök återstår innan du måste kontakta operatören för att låsa upp enheten.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-kortet är obrukbart. Kontakta operatören."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Du angav fel PUK-kod för SIM-kortet. <xliff:g id="NUMBER">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart."</item>
- <item quantity="other" msgid="5477305226026342036">"Du angav fel PUK-kod för SIM-kortet. <xliff:g id="NUMBER">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Du angav fel PUK-kod för SIM-kortet. <xliff:g id="NUMBER_1">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart.</item>
+ <item quantity="one">Du angav fel PUK-kod för SIM-kortet. <xliff:g id="NUMBER_0">%d</xliff:g> försök återstår innan SIM-kortet blir obrukbart.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Det gick inte att låsa upp med pinkoden för SIM-kortet."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Det gick inte att låsa upp med PUK-koden för SIM-kortet."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden godkändes!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjänst."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
</resources>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index bc8cffb..886c22e 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Umekosea katika kuweka mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> bila kufaulu, utaombwa kufungua kompyuta yako ndogo kwa kutumia akaunti yako ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> yasiyofaulu, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Msimbo wa PIN ya SIM usiosahihi sasa lazima uwasiliane na mtoa huduma wako ili ufungue kifaa chako."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Msimbo wa PIN ya SIM usio sahihi, umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g> kabla ulazimike kuwasiliana na mtoa huduma wako ili ufungue kifaa chako."</item>
- <item quantity="other" msgid="2215723361575359486">"Msimbo wa PIN ya SIM usio sahihi, umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Msimbo wa PIN ya SIM si sahihi, umebakisha majaribio <xliff:g id="NUMBER_1">%d</xliff:g>.</item>
+ <item quantity="one">Msimbo wa PIN ya SIM si sahihi, umebakisha majaribio <xliff:g id="NUMBER_0">%d</xliff:g> kabla ya kulazimika kuwasiliana na mtoa huduma wako ili afungue kifaa chako.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM haiwezi kutumika. Wasiliana na mtoa huduma wako."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Msimbo wa PUK ya SIM usio sahihi, umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa."</item>
- <item quantity="other" msgid="5477305226026342036">"Msimbo wa PUK ya SIM usio sahihi, umesalia na majaribio <xliff:g id="NUMBER">%d</xliff:g> kabla ya SIM kuacha kutumika kabisa."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Msimbo wa PUK ya SIM si sahihi, umebakisha majaribio <xliff:g id="NUMBER_1">%d</xliff:g> kabla SIM haijafungwa kabisa.</item>
+ <item quantity="one">Msimbo wa PUK ya SIM si sahihi, umebakisha majaribio <xliff:g id="NUMBER_0">%d</xliff:g> kabla SIM haijfungwa kabisa.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Utendakazi wa PIN ya SIM umeshindwa!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Utendakazi wa PUK ya SIM umeshindwa!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Msimbo Umekubaliwa!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Hakuna huduma."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index 761cea8..89c1480 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் டேப்லெட்டைத் திறக்க கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தின் தடையை நீக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தைத் திறக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளும் முன், மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
- <item quantity="other" msgid="2215723361575359486">"சிம் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">சிம்மின் பின் குறியீடு தவறானது, உங்களிடம் <xliff:g id="NUMBER_1">%d</xliff:g> முயற்சிகள் மீதமுள்ளன.</item>
+ <item quantity="one">சிம்மின் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER_0">%d</xliff:g> முயற்சிக்குப் பின்னர், சாதனத்தைத் திறக்க, கண்டிப்பாக உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"சிம் பயன்பாட்டிற்கு உகந்தது அல்ல. உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
- <item quantity="other" msgid="5477305226026342036">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">சிம் PUK குறியீடு தவறானது, நிரந்தரமாக சிம் முடக்கப்படும் முன், நீங்கள் <xliff:g id="NUMBER_1">%d</xliff:g> முறை முயற்சிக்கலாம்.</item>
+ <item quantity="one">சிம்மின் PUK குறியீடு தவறானது, நிரந்தரமாக சிம் முடக்கப்படும் முன், நீங்கள் <xliff:g id="NUMBER_0">%d</xliff:g> முறை முயற்சிக்கலாம்.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"சிம் பின் செயல்பாடு தோல்வி!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"சிம் PUK செயல்பாடு தோல்வி!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"குறியீடு ஏற்கப்பட்டது!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"சேவை இல்லை."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"உள்ளீட்டு முறையை மாற்றும் பொத்தான்."</string>
</resources>
diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml
index 67d843c..2f51742 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్ను అన్లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"మీరు మీ అన్లాక్ నమూనాను <xliff:g id="NUMBER_0">%d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్ను అన్లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"సిమ్ పిన్ కోడ్ చెల్లదు, మీరు ఇప్పుడు మీ పరికరాన్ని అన్లాక్ చేయడానికి తప్పనిసరిగా మీ క్యారియర్ను సంప్రదించండి."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"సిమ్ పిన్ కోడ్ చెల్లదు, మీరు మీ పరికరాన్ని అన్లాక్ చేయడానికి తప్పనిసరిగా మీ క్యారియర్ను సంప్రదించాల్సిన పరిస్థితి ఏర్పడకుండా ఉండటానికి మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది."</item>
- <item quantity="other" msgid="2215723361575359486">"సిమ్ పిన్ కోడ్ చెల్లదు, మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN కోడ్ చెల్లదు, మీకు <xliff:g id="NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి.</item>
+ <item quantity="one">SIM PIN కోడ్ చెల్లదు, మీరు మీ పరికరాన్ని అన్లాక్ చేయడానికి తప్పనిసరిగా మీ క్యారియర్ను సంప్రదించడానికి ముందు మీకు <xliff:g id="NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"సిమ్ నిరుపయోగమైనది. మీ క్యారియర్ను సంప్రదించండి."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"సిమ్ PUK కోడ్ చెల్లదు, సిమ్ శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది."</item>
- <item quantity="other" msgid="5477305226026342036">"సిమ్ PUK కోడ్ చెల్లదు, సిమ్ శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK కోడ్ చెల్లదు, SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి.</item>
+ <item quantity="one">SIM PUK కోడ్ చెల్లదు, SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"సిమ్ పిన్ చర్య విఫలమైంది!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"సిమ్ PUK చర్య విఫలమైంది!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"కోడ్ ఆమోదించబడింది!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"సేవ లేదు."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ఇన్పుట్ పద్ధతి మార్చే బటన్."</string>
</resources>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index ca2eab2..6d0d026 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"รหัส PIN ของซิมไม่ถูกต้อง ตอนนี้คุณต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ"</item>
- <item quantity="other" msgid="2215723361575359486">"รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้ง"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง</item>
+ <item quantity="one">รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"ซิมไม่สามารถใช้งานได้ ติดต่อผู้ให้บริการของคุณ"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"รหัส PUK ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร"</item>
- <item quantity="other" msgid="5477305226026342036">"รหัส PUK ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">รหัส PUK ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร</item>
+ <item quantity="one">รหัส PUK ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งก่อนที่ซิมจะไม่สามารถใช้งานได้อย่างถาวร</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"การปลดล็อกด้วย PIN ของซิมล้มเหลว!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"การปลดล็อกด้วย PUK ของซิมล้มเหลว!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"รหัสได้รับการยอมรับ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ไม่มีบริการ"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</string>
</resources>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 7dbc067..8125efe 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang tablet mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Maling PIN code ng SIM, dapat ka nang makipag-ugnay sa iyong carrier upang i-unlock ang iyong device."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Maling PIN code ng SIM, mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok bago ka dapat makipag-ugnay sa iyong carrier upang i-unlock ang iyong device."</item>
- <item quantity="other" msgid="2215723361575359486">"Maling PIN code ng SIM, mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Maling PIN code ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> natitirang pagsubok.</item>
+ <item quantity="other">Maling PIN code ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> na natitirang pagsubok.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"Hindi magagamit ang SIM. Makipag-ugnay sa iyong carrier."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Maling PUK code ng SIM, mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok bago maging permanenteng hindi magagamit ang SIM."</item>
- <item quantity="other" msgid="5477305226026342036">"Maling PUK code ng SIM, mayroon kang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok bago maging permanenteng hindi magagamit ang SIM."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Maling PUK code ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> natitirang pagsubok bago tuluyang hindi magamit ang SIM.</item>
+ <item quantity="other">Maling PUK code ng SIM, mayroon kang <xliff:g id="NUMBER_1">%d</xliff:g> na natitirang pagsubok bago tuluyang hindi magamit ang SIM.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Nabigo ang operasyon ng SIM PIN!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Nabigo ang operasyon ng SIM PUK!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Tinanggap ang Code!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Walang serbisyo."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
</resources>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index 5a13aa9..aa32baa 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -61,7 +61,7 @@
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Yanlış Desen"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Yanlış Şifre"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"Yanlış PIN"</string>
- <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> saniye içinde yeniden deneyin."</string>
+ <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"Deseninizi çizin"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN kodunu girin"</string>
<string name="kg_sim_pin_instructions_multi" msgid="7818515973197201434">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" için SIM PIN\'ini girin"</string>
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra, tabletinizi bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> saniye içinde tekrar deneyin."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Yanlış SIM PIN kodu. Cihazınızın kilidini açmak için artık operatörünüzle bağlantı kurmanız gerekiyor."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Yanlış SIM PIN kodu. Cihazının kilidini açmak için operatörünüzle bağlantı kurmak zorunda kalmadan önce <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- <item quantity="other" msgid="2215723361575359486">"Yanlış SIM PIN kodu. <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Yanlış SIM PIN kodu, <xliff:g id="NUMBER_1">%d</xliff:g> deneme hakkınız kaldı.</item>
+ <item quantity="one">Yanlış SIM PIN kodu. Cihazınızın kilidini açmak için operatörünüzle bağlantı kurmak zorunda kalmadan önce <xliff:g id="NUMBER_0">%d</xliff:g> deneme hakkınız kaldı.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM kullanılamaz. Operatörünüzle bağlantı kurun."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Yanlış SIM PUK kodu. SIM kalıcı olarak kullanılmaz hale gelmeden önce <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- <item quantity="other" msgid="5477305226026342036">"Yanlış SIM PUK kodu. SIM kalıcı olarak kullanılmaz hale gelmeden önce <xliff:g id="NUMBER">%d</xliff:g> deneme hakkınız kaldı."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Yanlış SIM PUK kodu, SIM kalıcı olarak kullanılmaz hale gelmeden önce <xliff:g id="NUMBER_1">%d</xliff:g> deneme hakkınız kaldı.</item>
+ <item quantity="one">Yanlış SIM PUK kodu, SIM kalıcı olarak kullanılmaz hale gelmeden önce <xliff:g id="NUMBER_0">%d</xliff:g> deneme hakkınız kaldı.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN işlemi başarısız oldu!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK işlemi başarısız oldu!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Kabul Edildi!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Hizmet yok."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Giriş yöntemini değiştirme düğmesi."</string>
</resources>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index cb51ec4..9e52283 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -95,17 +95,22 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати планшетний ПК за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Неправильний PIN-код SIM-карти. Зв’яжіться зі своїм оператором, щоб розблокувати пристрій."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Неправильний PIN-код SIM-карти. У вас залишилась <xliff:g id="NUMBER">%d</xliff:g> спроба. Після цього потрібно буде зв’язатися з оператором, щоб розблокувати пристрій."</item>
- <item quantity="other" msgid="2215723361575359486">"Неправильний PIN-код SIM-карти. У вас залишилося стільки спроб: <xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Неправильний PIN-код SIM-карти. У вас залишилась <xliff:g id="NUMBER_1">%d</xliff:g> спроба.</item>
+ <item quantity="few">Неправильний PIN-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби.</item>
+ <item quantity="many">Неправильний PIN-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроб.</item>
+ <item quantity="other">Неправильний PIN-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM-карту заблоковано. Зв’яжіться з оператором."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Неправильний PUK-код SIM-карти. У вас залишилась <xliff:g id="NUMBER">%d</xliff:g> спроба. Після цього SIM-карту буде назавжди заблоковано."</item>
- <item quantity="other" msgid="5477305226026342036">"Неправильний PUK-код SIM-карти. У вас залишилося стільки спроб: <xliff:g id="NUMBER">%d</xliff:g>. Після цього SIM-карту буде назавжди заблоковано."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Неправильний PUK-код SIM-карти. У вас залишилася <xliff:g id="NUMBER_1">%d</xliff:g> спроба. Після цього SIM-карту буде назавжди заблоковано.</item>
+ <item quantity="few">Неправильний PUK-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде назавжди заблоковано.</item>
+ <item quantity="many">Неправильний PUK-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроб. Після цього SIM-карту буде назавжди заблоковано.</item>
+ <item quantity="other">Неправильний PUK-код SIM-карти. У вас залишилося <xliff:g id="NUMBER_1">%d</xliff:g> спроби. Після цього SIM-карту буде назавжди заблоковано.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Помилка введення PIN-коду SIM-карти."</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Помилка введення PUK-коду SIM-карти."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код прийнято."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Зв’язку немає."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</string>
</resources>
diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml
index 0daa46b..5cd54c0 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا ٹیبلیٹ غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"غلط SIM PIN کوڈ اب آپ کو اپنا آلہ غیر مقفل کرنے کیلئے لازمی طور پر اپنے کیریئر سے رابطہ کرنا چاہئے۔"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"غلط SIM PIN کوڈ، اس سے پہلے کہ آپ اپنا آلہ غیر مقفل کرنے کیلئے لازمی طور پر اپنے کیریئر سے رابطہ کریں آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوشش بچی ہے۔"</item>
- <item quantity="other" msgid="2215723361575359486">"غلط SIM PIN کوڈ، آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوششیں بچی ہیں۔"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">غلط SIM PIN کوڈ، آپ کے پاس <xliff:g id="NUMBER_1">%d</xliff:g> کوششیں بچی ہیں۔</item>
+ <item quantity="one">غلط SIM PIN کوڈ، آپ کے پاس <xliff:g id="NUMBER_0">%d</xliff:g> کوشش بچی ہے، اس کے بعد آپ کو اپنا آلہ غیر مقفل کرنے کیلئے اپنے کریئر سے رابطہ کرنا ہوگا۔</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM ناقابل استعمال ہے۔ اپنے کیریئر رابطہ کریں۔"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"غلط SIM PUK کوڈ، SIM مستقل طور پر ناقابل استعمال ہونے سے پہلے آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوشش بچی ہے۔"</item>
- <item quantity="other" msgid="5477305226026342036">"غلط SIM PUK کوڈ، SIM مستقل طور پر ناقابل استعمال ہونے سے پہلے آپ کے پاس <xliff:g id="NUMBER">%d</xliff:g> کوششیں بچی ہیں۔"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">غلط SIM PUK کوڈ، آپ کے پاس <xliff:g id="NUMBER_1">%d</xliff:g> کوششیں بچی ہیں، اس کے بعد SIM مستقل طور پر ناقابل استعمال ہو جائے گا۔</item>
+ <item quantity="one">SIM کا غلط PUK کوڈ، آپ ک پاس <xliff:g id="NUMBER_0">%d</xliff:g> کوشش بچی ہے، اس کے بعد SIM مستقل طور پر ناقابل استعمال ہو جائے گا۔</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN کارروائی ناکام ہو گئی!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK کارروائی ناکام ہو گئی!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"کوڈ قبول کر لیا گیا!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"کوئی سروس نہیں ہے۔"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"اندراج کا طریقہ سوئچ کرنے کا بٹن۔"</string>
</resources>
diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml
index 31eb593..a6852a7 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Chizmali parolni <xliff:g id="NUMBER_0">%d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Chizmali parolni <xliff:g id="NUMBER_0">%d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM karta PIN kodi noto‘g‘ri. Qurilma qulfini ochish uchun aloqa operatoringiz bilan bog‘laning."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM karta PIN kodi noto‘g‘ri terildi, yana <xliff:g id="NUMBER">%d</xliff:g> marta uirinib ko‘rishingiz mumkin, urinishlar tugagandan keyin qurilmangizni qulfdan chiqarish uchun aloqa operatoringiz bilan bog‘lanishingiz kerak."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM karta PIN kodi noto‘g‘ri terildi, yana <xliff:g id="NUMBER">%d</xliff:g> marta urinib ko‘rishingiz mumkin."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM kartaning PIN kodi noto‘g‘ri. Sizda yana <xliff:g id="NUMBER_1">%d</xliff:g> ta urinish qoldi.</item>
+ <item quantity="one">SIM kartaning PIN kodi noto‘g‘ri. Qurilmani qulfdan chiqarish uchun sizda yana <xliff:g id="NUMBER_0">%d</xliff:g> ta urinish qoldi.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM kartadan foydalanib bo‘lmaydi. Aloqa operatoringiz bilan bog‘laning."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM karta PUK kodi noto‘g‘ri terildi, yana <xliff:g id="NUMBER">%d</xliff:g> marta urinib ko‘rganingizdan so‘ng, SIM kartadan umuman foydalanib bo‘lmaydi."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM karta PUK kodi noto‘g‘ri terildi, yana <xliff:g id="NUMBER">%d</xliff:g> marta urinib ko‘rganingizdan so‘ng, SIM kartadan umuman foydalanib bo‘lmaydi."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM kartaning PUK kodi noto‘g‘ri kiritildi. Yana <xliff:g id="NUMBER_1">%d</xliff:g> ta muvaffaqiyatsiz urinishdan so‘ng SIM karta butunlay ishdan chiqadi.</item>
+ <item quantity="one">SIM kartaning PUK kodi noto‘g‘ri kiritildi. Yana <xliff:g id="NUMBER_0">%d</xliff:g> ta muvaffaqiyatsiz urinishdan so‘ng SIM karta butunlay ishdan chiqadi.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM karta PIN jarayoni amalga oshmadi!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM karta PUK jarayoni amalga oshmadi!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod qabul qilindi!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aloqa yo‘q."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Kiritish uslubi tugmasini almashtirish."</string>
</resources>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 0dcbaad..5727900 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng tài khoản email.\n\n Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Bạn đã <xliff:g id="NUMBER_0">%d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Vui lòng thử lại sau <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Mã PIN của SIM không chính xác, bây giờ bạn phải liên hệ với nhà cung cấp dịch vụ để mở khóa thiết bị của bạn."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Mã PIN của SIM không chính xác, bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử trước khi bạn phải liên hệ với nhà cung cấp dịch vụ để mở khóa thiết bị của bạn."</item>
- <item quantity="other" msgid="2215723361575359486">"Mã PIN của SIM không chính xác, bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">Mã PIN của SIM không chính xác, bạn còn <xliff:g id="NUMBER_1">%d</xliff:g> lần thử.</item>
+ <item quantity="one">Mã PIN của SIM không chính xác, bạn còn <xliff:g id="NUMBER_0">%d</xliff:g> lần thử trước khi bạn phải liên hệ với nhà cung cấp dịch vụ để mở khóa thiết bị của mình.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM không thể sử dụng được. Liên hệ với nhà cung cấp dịch vụ của bạn."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Mã PUK của SIM không chính xác, bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không thể sử dụng được."</item>
- <item quantity="other" msgid="5477305226026342036">"Mã PUK của SIM không chính xác, bạn còn <xliff:g id="NUMBER">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không thể sử dụng được."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">Mã PUK của SIM không chính xác, bạn còn <xliff:g id="NUMBER_1">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không sử dụng được.</item>
+ <item quantity="one">Mã PUK của SIM không chính xác, bạn còn <xliff:g id="NUMBER_0">%d</xliff:g> lần thử trước khi SIM vĩnh viễn không thể sử dụng được.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Thao tác mã PIN của SIM không thành công!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Thao tác mã PUK của SIM không thành công!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Mã được chấp nhận!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Không có dịch vụ."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
</resources>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 9f9f970..a93b54b 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁平板电脑。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已经 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐户解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒后重试。"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM卡PIN码不正确,您现在必须联系运营商为您解锁设备。"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM卡PIN码不正确,您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。如果仍然失败,则必须联系运营商帮您解锁设备。"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM卡PIN码不正确,您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM 卡 PIN 码不正确,您还可尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
+ <item quantity="one">SIM 卡 PIN 码不正确,您还可尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,则需要联系运营商帮您解锁设备。</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM卡无法使用,请与您的运营商联系。"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM卡PUK码不正确,您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。如果仍然失败,SIM卡将永远无法使用。"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM卡PUK码不正确,您还有<xliff:g id="NUMBER">%d</xliff:g>次尝试机会。如果仍然失败,SIM卡将永远无法使用。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM 卡 PUK 码不正确,您还可尝试 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍不正确,SIM 卡将永远无法使用。</item>
+ <item quantity="one">SIM 卡 PUK 码不正确,您还可尝试 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍不正确,SIM 卡将永远无法使用。</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM卡PIN码操作失败!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM卡PUK码操作失败!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"代码正确!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"无服务。"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</string>
</resources>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index 2aa5d62..55a6a5e 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的平板電腦。\n\n請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的手機。\n\n請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN 碼不正確,您現在必須聯絡流動網絡供應商為您的裝置解鎖。"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN 碼不正確,您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN 碼不正確,您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM PIN 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次機會輸入。</item>
+ <item quantity="one">SIM PIN 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,您必須聯絡流動網絡供應商為您的裝置解鎖。</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM 無法使用,請聯絡您的流動網絡供應商。"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK 碼不正確,您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。如果仍然輪入錯誤,SIM 將永久無法使用。"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK 碼不正確,您剩下 <xliff:g id="NUMBER">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 將永久無法使用。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM PUK 碼不正確,您還有 <xliff:g id="NUMBER_1">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 卡將永久無法使用。</item>
+ <item quantity="one">SIM PUK 碼不正確,您還有 <xliff:g id="NUMBER_0">%d</xliff:g> 次機會輸入。如果仍然輸入錯誤,SIM 卡將永久無法使用。</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN 碼操作失敗!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK 碼操作失敗!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
</resources>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index f9a8cdb..66c665f 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除平板電腦的鎖定狀態。\n\n請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"您的解鎖圖形已畫錯 <xliff:g id="NUMBER_0">%d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%d</xliff:g> 次仍未成功,系統就會要求您透過電子郵件帳戶解除手機的鎖定狀態。\n\n請在 <xliff:g id="NUMBER_2">%d</xliff:g> 秒後再試一次。"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM 卡的 PIN 碼輸入錯誤,您現在必須請行動通訊業者為裝置解鎖。"</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM 卡的 PIN 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。如果仍然失敗,就必須請行動通訊業者為裝置解鎖。"</item>
- <item quantity="other" msgid="2215723361575359486">"SIM 卡的 PIN 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="other">SIM 卡的 PIN 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。</item>
+ <item quantity="one">SIM 卡的 PIN 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,就必須請行動通訊業者為裝置解鎖。</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM 卡無法使用,請與您的行動通訊業者聯絡。"</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM 卡的 PUK 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。"</item>
- <item quantity="other" msgid="5477305226026342036">"SIM 卡的 PUK 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。"</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="other">SIM 卡的 PUK 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER_1">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item>
+ <item quantity="one">SIM 卡的 PUK 碼輸入錯誤,您還可以再試 <xliff:g id="NUMBER_0">%d</xliff:g> 次。如果仍然失敗,SIM 卡將永久無法使用。</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM 卡 PIN 碼操作失敗!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM 卡 PUK 碼操作失敗!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
</resources>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index 4c8f757..be8900a 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -95,17 +95,18 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Udwebe ngokungalungile iphathini yakho yokuvula izikhathi ezingu-<xliff:g id="NUMBER_0">%d</xliff:g>. Emva <xliff:g id="NUMBER_1">%d</xliff:g> kweminye imizamo engaphumelelanga, uzocelwa ukuvula ithebhulethi yakho usebenzisa ukungena ngemvume kwi-Google.\n\n Sicela uzame futhi emuva kwamasekhondi angu-<xliff:g id="NUMBER_2">%d</xliff:g>"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%d</xliff:g> amasekhondi."</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Ikhodi yephinikhodi ye-SIM engalungile manje kumele uxhumane nenkampini yenethiwekhi yakho ukuvula idivayisi yakho."</string>
- <plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"Ikhodi yephinikhodi ye-SIM engalungile, unemizamo engu-<xliff:g id="NUMBER">%d</xliff:g> esele ngaphambi kokuba uxhumane nenkampini yenethiwekhi."</item>
- <item quantity="other" msgid="2215723361575359486">"Ikhodi yephinikhodi ye-SIM engalungile, unemizamo esele engu-<xliff:g id="NUMBER">%d</xliff:g>."</item>
- </plurals>
+ <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
+ <item quantity="one">Ikhodi engalungile yephinikhodi ye-SIM, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele.</item>
+ <item quantity="other">Ikhodi engalungile yephinikhodi ye-SIM, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele.</item>
+ </plurals>
<string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"I-SIM ayisebenziseki. Xhumana nemkampini yenethiwekhi yakho."</string>
- <plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"Ikhodi ye-PUK ye-SIM engalungile, unemizamo engu-<xliff:g id="NUMBER">%d</xliff:g> esele ngaphambi kokuba i-SIM ibe engasebenziseki unaphakade."</item>
- <item quantity="other" msgid="5477305226026342036">"Ikhodi ye-PUK ye-SIM engalungile, unemizamo engu-<xliff:g id="NUMBER">%d</xliff:g> esele ngaphambi kokuba i-SIM iba engasebenziseki unaphakade."</item>
- </plurals>
+ <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="7576227366999858780">
+ <item quantity="one">Ikhodi ye-PUK ye-SIM engalungile, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasasebenziseki unaphakade.</item>
+ <item quantity="other">Ikhodi ye-PUK ye-SIM engalungile, unemizamo engu-<xliff:g id="NUMBER_1">%d</xliff:g> esele ngaphambi kokuthi i-SIM ingasasebenziseki unaphakade.</item>
+ </plurals>
<string name="kg_password_pin_failed" msgid="6268288093558031564">"Umsebenzi wephinikhodi ye-SIM wehlulekile!"</string>
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Umsebenzi we-PUK ye-SIM wehlulekile!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Ikhodi yamukelwe!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ayikho isevisi."</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
</resources>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 8b18b2ed..5047330 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -297,4 +297,7 @@
This is displayed if the phone is not connected to a carrier.-->
<string name="keyguard_carrier_default">No service.</string>
+ <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">Switch input method button.</string>
+
</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 7c56e84..bca0305 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -17,11 +17,7 @@
package com.android.keyguard;
import android.content.Context;
-import android.database.ContentObserver;
import android.graphics.Rect;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
@@ -32,39 +28,19 @@
public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
implements View.OnKeyListener {
- private final android.database.ContentObserver mSpeakPasswordObserver
- = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- // Ensure that it's not called too early
- if (mButton0 != null) {
- mButton0.updateContentDescription();
- mButton1.updateContentDescription();
- mButton2.updateContentDescription();
- mButton3.updateContentDescription();
- mButton4.updateContentDescription();
- mButton5.updateContentDescription();
- mButton6.updateContentDescription();
- mButton7.updateContentDescription();
- mButton8.updateContentDescription();
- mButton9.updateContentDescription();
- }
- }
- };
protected PasswordTextView mPasswordEntry;
private View mOkButton;
private View mDeleteButton;
- private NumPadKey mButton0;
- private NumPadKey mButton1;
- private NumPadKey mButton2;
- private NumPadKey mButton3;
- private NumPadKey mButton4;
- private NumPadKey mButton5;
- private NumPadKey mButton6;
- private NumPadKey mButton7;
- private NumPadKey mButton8;
- private NumPadKey mButton9;
+ private View mButton0;
+ private View mButton1;
+ private View mButton2;
+ private View mButton3;
+ private View mButton4;
+ private View mButton5;
+ private View mButton6;
+ private View mButton7;
+ private View mButton8;
+ private View mButton9;
public KeyguardPinBasedInputView(Context context) {
this(context, null);
@@ -72,9 +48,6 @@
public KeyguardPinBasedInputView(Context context, AttributeSet attrs) {
super(context, attrs);
- context.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD), true,
- mSpeakPasswordObserver, UserHandle.USER_ALL);
}
@Override
@@ -215,16 +188,16 @@
}
});
- mButton0 = (NumPadKey) findViewById(R.id.key0);
- mButton1 = (NumPadKey) findViewById(R.id.key1);
- mButton2 = (NumPadKey) findViewById(R.id.key2);
- mButton3 = (NumPadKey) findViewById(R.id.key3);
- mButton4 = (NumPadKey) findViewById(R.id.key4);
- mButton5 = (NumPadKey) findViewById(R.id.key5);
- mButton6 = (NumPadKey) findViewById(R.id.key6);
- mButton7 = (NumPadKey) findViewById(R.id.key7);
- mButton8 = (NumPadKey) findViewById(R.id.key8);
- mButton9 = (NumPadKey) findViewById(R.id.key9);
+ mButton0 = findViewById(R.id.key0);
+ mButton1 = findViewById(R.id.key1);
+ mButton2 = findViewById(R.id.key2);
+ mButton3 = findViewById(R.id.key3);
+ mButton4 = findViewById(R.id.key4);
+ mButton5 = findViewById(R.id.key5);
+ mButton6 = findViewById(R.id.key6);
+ mButton7 = findViewById(R.id.key7);
+ mButton8 = findViewById(R.id.key8);
+ mButton9 = findViewById(R.id.key9);
mPasswordEntry.requestFocus();
super.onFinishInflate();
diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
index 70a4108..681db80 100644
--- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
+++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java
@@ -22,8 +22,6 @@
import android.os.Debug;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -120,17 +118,7 @@
}
setBackground(mContext.getDrawable(R.drawable.ripple_drawable));
- updateContentDescription();
- }
-
- public void updateContentDescription() {
- if (shouldSpeakPasswordsForAccessibility()) {
- setContentDescription(
- mDigitText.getText().toString() + mKlondikeText.getText().toString());
- } else {
- setContentDescription(getContext().getString(
- com.android.internal.R.string.keyboard_password_character_no_headset));
- }
+ setContentDescription(mDigitText.getText().toString());
}
@Override
@@ -164,15 +152,6 @@
mKlondikeText.layout(left, top, left + mKlondikeText.getMeasuredWidth(), bottom);
}
- /**
- * @return true if the user has explicitly allowed accessibility services
- * to speak passwords.
- */
- private boolean shouldSpeakPasswordsForAccessibility() {
- return (Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0, UserHandle.USER_CURRENT) == 1);
- }
-
@Override
public boolean hasOverlappingRendering() {
return false;
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 169710a..482bd22 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Voeg drukker by"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Kies drukker"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Vergeet drukker"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> drukker gekry"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> drukkers gekry"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> drukkers gevind</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> drukker gevind</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Kies drukdiens"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Soek tans vir drukkers"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Geen drukkers gekry nie"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kanselleer tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Drukkerfout by <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drukker het <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> geblokkeer"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>-uitdruktaak"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>-uitdruktake"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-druktake</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>-druktaak</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Kanselleer"</string>
<string name="restart" msgid="2472034227037808749">"Herbegin"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met drukker nie"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index 7d9b5f3..588c337 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"አታሚ አክል"</string>
<string name="print_select_printer" msgid="7388760939873368698">"አታሚ ምረጥ"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"አታሚ እርሳ"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚ ተገኝቷል"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚዎች ተገኝተዋል"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"የህትመት አገልግሎት ይምረጡ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"አታሚዎችን በመፈለግ ላይ"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ምንም አታሚዎች አልተገኙም"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> የህትመት ስራ"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> የህትመት ስራዎች"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> የህትመት ስራ</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> የህትመት ስራ</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ይቅር"</string>
<string name="restart" msgid="2472034227037808749">"እንደገና ጀምር"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ከአታሚ ጋር ምንም ግንኙነት የለም"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 217d070..83d5994 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -54,10 +54,14 @@
<string name="print_add_printer" msgid="1088656468360653455">"إضافة طابعة"</string>
<string name="print_select_printer" msgid="7388760939873368698">"حدد الطابعة"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"تجاهل الطابعة"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> طابعة"</item>
- <item quantity="other" msgid="6533817036607128241">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> من الطابعات"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="zero">لم يتم العثور على أية طابعة (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
+ <item quantity="two">تم العثور على طابعتين (<xliff:g id="COUNT_1">%1$s</xliff:g>)</item>
+ <item quantity="few">تم العثور على <xliff:g id="COUNT_1">%1$s</xliff:g> طابعات</item>
+ <item quantity="many">تم العثور على <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_0">%1$s</xliff:g>)</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"اختر خدمة طباعة"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"البحث عن طابعات"</string>
<string name="print_no_printers" msgid="4869403323900054866">"لم يتم العثور على طابعات"</string>
@@ -65,10 +69,14 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> مهمة طباعة"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> من مهام الطباعة"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="zero"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهمة طباعة</item>
+ <item quantity="two">مهمتا طباعة (<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>)</item>
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهام طباعة</item>
+ <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهمة طباعة</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> من مهام الطباعة</item>
+ <item quantity="one">مهمة طباعة واحدة (<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>)</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"إلغاء"</string>
<string name="restart" msgid="2472034227037808749">"إعادة تشغيل"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"لا يوجد اتصال بالطابعة"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index c84f47d..5df95cb 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Добавяне на принтер"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Избиране на принтер"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Забравяне на принтера"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Намерен е <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item>
- <item quantity="other" msgid="6533817036607128241">"Намерени са <xliff:g id="COUNT">%1$s</xliff:g> принтера"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Намерени са <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ <item quantity="one">Намерен е <xliff:g id="COUNT_0">%1$s</xliff:g> принтер</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Избиране на услуга за отпечатване"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Търсят се принтери"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Няма намерени принтери"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Задание за отпечатване: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Задания за отпечатване: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Задания за отпечатване: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Задание за отпечатване: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Отказ"</string>
<string name="restart" msgid="2472034227037808749">"Рестартиране"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Няма връзка с принтера"</string>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 6e03179..cf6ed72 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"মুদ্রক যোগ করুন"</string>
<string name="print_select_printer" msgid="7388760939873368698">"মুদ্রক নির্বাচন করুন"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"মুদ্রকটিকে সরিয়ে দিন"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g>টি মুদ্রক খুঁজে পাওয়া গেছে"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g>টি মুদ্রক খুঁজে পাওয়া গেছে"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"মুদ্রণ পরিষেবা চয়ন করুন"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"মুদ্রকগুলি অনুসন্ধান করা হচ্ছে"</string>
<string name="print_no_printers" msgid="4869403323900054866">"কোনো মুদ্রক পাওয়া যায়নি"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> মুদ্রণ কার্য"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> মুদ্রণ কার্যগুলি"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> মুদ্রণ কার্যগুলি</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> মুদ্রণ কার্যগুলি</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"বাতিল করুন"</string>
<string name="restart" msgid="2472034227037808749">"পুনর্সূচনা"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"মুদ্রকে কোনো সংযোগ নেই"</string>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index 0ecaf1a..04c3b90 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Afegeix una impressora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Selecciona una impressora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Esborra la impressora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"S\'ha trobat <xliff:g id="COUNT">%1$s</xliff:g> impressora"</item>
- <item quantity="other" msgid="6533817036607128241">"S\'han trobat <xliff:g id="COUNT">%1$s</xliff:g> impressores"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">S\'han trobat <xliff:g id="COUNT_1">%1$s</xliff:g> impressores</item>
+ <item quantity="one">S\'ha trobat <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Selecció del servei d\'impressió"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Cerca d\'impressores"</string>
<string name="print_no_printers" msgid="4869403323900054866">"No s\'ha trobat cap impressora"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"S\'està cancel·lant <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error d\'impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impressora bloquejada <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tasca d\'impressió per a <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tasques d\'impressió per a <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tasques d\'impressió</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tasca d\'impressió</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel·la"</string>
<string name="restart" msgid="2472034227037808749">"Reinicia"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hi ha connexió amb la impressora"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index f26c21c..ca528c1 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Přidat tiskárnu"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Vybrat tiskárnu"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Odstranit tiskárnu"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- <item quantity="other" msgid="6533817036607128241">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="few">Nalezené tiskárny: <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="many">Nalezené tiskárny: <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="other">Nalezené tiskárny: <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="one">Nalezené tiskárny: <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Zvolte službu tisku"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhledávání tiskáren"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nebyly nalezeny žádné tiskárny"</string>
@@ -65,10 +67,12 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Rušení úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tiskárny u úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tiskárna blokuje úlohu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Počet tiskových úloh: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Počet tiskových úloh: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="few">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="many">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Zrušit"</string>
<string name="restart" msgid="2472034227037808749">"Restartovat"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nelze se připojit k tiskárně"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 339485a..6b539d7 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Tilføj printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Vælg printer"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Glem printer"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printer"</item>
- <item quantity="other" msgid="6533817036607128241">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printere"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Der blev fundet <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+ <item quantity="other">Der blev fundet <xliff:g id="COUNT_1">%1$s</xliff:g> printere</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Vælg udskriftstjeneste"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søger efter printere"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Der blev ikke fundet nogen printere"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annulleres"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Udskriften <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> mislykkedes"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeren har blokeret <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>-udskriftsjob"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>-udskriftsjobs"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-udskriftsjob</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-udskriftsjob</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuller"</string>
<string name="restart" msgid="2472034227037808749">"Genstart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse til printer"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index d1ff80a..e3894c4 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Drucker hinzufügen"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Drucker auswählen"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Drucker wieder vergessen"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> Drucker gefunden</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> Drucker gefunden</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Druckdienst auswählen"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Suche nach Druckern"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Keine Drucker gefunden"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird abgebrochen..."</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Druckerfehler <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drucker hat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> blockiert."</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Druckauftrag \"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>\""</item>
- <item quantity="other" msgid="8746611264734222865">"Druckaufträge \"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>\""</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Druckaufträge \"<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>\"</item>
+ <item quantity="one">Druckauftrag \"<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>\"</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Abbrechen"</string>
<string name="restart" msgid="2472034227037808749">"Neu starten"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Keine Verbindung zum Drucker"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 7181402..ff2fe4e 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Προσθήκη εκτυπωτή"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Επιλογή εκτυπωτή"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Διαγραφή εκτυπωτή"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Βρέθηκε <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτής"</item>
- <item quantity="other" msgid="6533817036607128241">"Βρέθηκαν <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτές"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Βρέθηκαν <xliff:g id="COUNT_1">%1$s</xliff:g> εκτυπωτές</item>
+ <item quantity="one">Βρέθηκε <xliff:g id="COUNT_0">%1$s</xliff:g> εκτυπωτής</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Επιλέξτε υπηρεσία εκτύπωσης"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Αναζήτηση για εκτυπωτές"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Δεν βρέθηκαν εκτυπωτές"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"εργασία εκτύπωσης <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"εργασίες εκτύπωσης <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> εργασίες εκτύπωσης</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> εργασία εκτύπωσης</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Ακύρωση"</string>
<string name="restart" msgid="2472034227037808749">"Επανεκκίνηση"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Δεν υπάρχει σύνδεση με εκτυπωτή"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 56b97b9..e5721b2 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printer found</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
<string name="print_no_printers" msgid="4869403323900054866">"No printers found"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blocked <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> print job"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> print jobs"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> print jobs</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> print job</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel"</string>
<string name="restart" msgid="2472034227037808749">"Restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 56b97b9..e5721b2 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printer found</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
<string name="print_no_printers" msgid="4869403323900054866">"No printers found"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blocked <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> print job"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> print jobs"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> print jobs</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> print job</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel"</string>
<string name="restart" msgid="2472034227037808749">"Restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 0229b9c..cc275de 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Agregar impresora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"No recordar impresora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Se encontró <xliff:g id="COUNT">%1$s</xliff:g> impresora."</item>
- <item quantity="other" msgid="6533817036607128241">"Se encontraron <xliff:g id="COUNT">%1$s</xliff:g> impresoras."</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Se encontraron <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras.</item>
+ <item quantity="one">Se encontró <xliff:g id="COUNT_0">%1$s</xliff:g> impresora.</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Elegir servicio de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
<string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La impresora bloqueó <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>."</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Trabajo de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Trabajos de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Trabajos de impresión: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Trabajo de impresión: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora."</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 87ecfe9..13417a4 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Añadir impresora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Borrar impresora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Se ha encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresora"</item>
- <item quantity="other" msgid="6533817036607128241">"Se han encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresoras"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Se han encontrado <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+ <item quantity="one">Se ha encontrado <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Seleccionar servicio de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
<string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La impresora ha bloqueado <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Trabajo de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Trabajos de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Trabajos de impresión <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Trabajo de impresión <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Volver a empezar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora"</string>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 5ee0070..dde4f3b 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Lisa printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Printeri valimine"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Printeri unustamine"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printer"</item>
- <item quantity="other" msgid="6533817036607128241">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printerit"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Leiti <xliff:g id="COUNT_1">%1$s</xliff:g> printerit</item>
+ <item quantity="one">Leiti <xliff:g id="COUNT_0">%1$s</xliff:g> printer</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Prinditeenuse valimine"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerite otsimine"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Printereid ei leitud"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> tühistamine"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri viga: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blokeeris töö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Prinditööd <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prinditööd</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> prinditöö</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Tühista"</string>
<string name="restart" msgid="2472034227037808749">"Taaskäivita"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printeriühendus puudub"</string>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index 4357bf4..3cc1b64 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Gehitu inprimagailua"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Hautatu inprimagailua"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Ahaztu inprimagailua"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> inprimagailu aurkitu da"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> inprimagailu aurkitu dira"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> inprimagailu aurkitu dira</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> inprimagailu aurkitu da</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Aukeratu inprimatze-zerbitzua"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inprimagailuak bilatzen"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Ez da inprimagailurik aurkitu"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bertan behera uzten"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errorea <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzean"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Inprimag. <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> blokeatu du"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> inprimatze-lana"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> inprimatze-lanak"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> inprimatze-lanak</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> inprimatze-lana</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Utzi"</string>
<string name="restart" msgid="2472034227037808749">"Berrabiarazi"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Inprimagailua ez dago konektatuta"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index e205050..c47a75a 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"افزودن چاپگر"</string>
<string name="print_select_printer" msgid="7388760939873368698">"انتخاب چاپگر"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"فراموش کردن چاپگر"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"انتخاب سرویس چاپ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"در حال جستجو برای چاپگرها"</string>
<string name="print_no_printers" msgid="4869403323900054866">"هیچ چاپگری یافت نشد"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"کار چاپ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"کارهای چاپ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one">کار چاپ <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">کار چاپ <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"لغو"</string>
<string name="restart" msgid="2472034227037808749">"راهاندازی مجدد"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"اتصال با چاپگر برقرار نیست"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 8af0bb4..6c88534 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Lisää tulostin"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Valitse tulostin"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Unohda tulostin"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostin"</item>
- <item quantity="other" msgid="6533817036607128241">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostinta"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> tulostinta löydetty</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> tulostin löydetty</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Valitse tulostuspalvelu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Etsitään tulostimia"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Tulostimia ei löydy"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Peruutetaan työ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Tulostinvirhe työlle <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tulostin esti työn <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tulostustyö <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tulostustyöt <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tulostustyötä</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tulostustyö</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Peruuta"</string>
<string name="restart" msgid="2472034227037808749">"Käynnistä uudelleen"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ei yhteyttä tulostimeen"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index ed605e8..dbc1ea3 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Sélectionner une imprimante"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvées</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours..."</string>
<string name="print_no_printers" msgid="4869403323900054866">"Aucune imprimante trouvée"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression : « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impression de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> » bloquée"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tâche d\'impression <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tâches d\'impression <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâche d\'impression</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâches d\'impression</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuler"</string>
<string name="restart" msgid="2472034227037808749">"Recommencer"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index a88b3f2c..cc0c352 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Sélectionner une imprimante"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée."</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées."</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes trouvées</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Aucune imprimante trouvée"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression pour \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" bloquée"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> tâche d\'impression"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> tâches d\'impression"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâche d\'impression</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâches d\'impression</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuler"</string>
<string name="restart" msgid="2472034227037808749">"Redémarrer"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante."</string>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index c5a271a..0e3d9f5 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Engadir impresora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impresora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Encontrouse <xliff:g id="COUNT">%1$s</xliff:g> impresora"</item>
- <item quantity="other" msgid="6533817036607128241">"Encontráronse <xliff:g id="COUNT">%1$s</xliff:g> impresoras"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Encontráronse <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item>
+ <item quantity="one">Encontrouse <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Escoller servizo de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Busca de impresoras"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Non se atopou ningunha impresora"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impresora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Traballo de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Traballos de impresión <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> traballos de impresión</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> traballo de impresión</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Non hai conexión coa impresora"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 6bf4aa8..5d8c3c6 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"प्रिंटर जोड़ें"</string>
<string name="print_select_printer" msgid="7388760939873368698">"प्रिंटर चुनें"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"प्रिंटर को भूल जाएं"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिला"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिले"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"प्रिंट सेवा चुनें"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर खोज रहा है"</string>
<string name="print_no_printers" msgid="4869403323900054866">"कोई प्रिंटर नहीं मिले"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> प्रिंट कार्य"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> प्रिंट कार्य"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"रहने दें"</string>
<string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटर के लिए कोई कनेक्शन नहीं"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index eddff9af..79eb2eb 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -54,10 +54,11 @@
<string name="print_add_printer" msgid="1088656468360653455">"Dodaj pisač"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Odaberite pisač"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Zaboravite pisač"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Pronađen je <xliff:g id="COUNT">%1$s</xliff:g> pisač"</item>
- <item quantity="other" msgid="6533817036607128241">"Pronađen je sljedeći broj pisača: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Pronađen je <xliff:g id="COUNT_1">%1$s</xliff:g> pisač</item>
+ <item quantity="few">Pronađena su <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+ <item quantity="other">Pronađeno je <xliff:g id="COUNT_1">%1$s</xliff:g> pisača</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Odaberite uslugu ispisa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje pisača"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nije pronađen nijedan pisač"</string>
@@ -65,10 +66,11 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje zadatka <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Pogreška pisača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Pisač je blokirao <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Zadatak ispisa <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Broj zadataka ispisa: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadatak ispisa</item>
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadatka ispisa</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadataka ispisa</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Odustani"</string>
<string name="restart" msgid="2472034227037808749">"Ponovo pokreni"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nema veze s pisačem"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 08a36b3..91182cf 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Nyomtató hozzáadása"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Nyomtató kiválasztása"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Nyomtató elfelejtése"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> nyomtató észlelve</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> nyomtató észlelve</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Nyomtatási szolgáltatás kiválasztása"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Nyomtatók keresése"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nem található nyomtató"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> törlése"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Nyomtatási hiba: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> letiltva."</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> – nyomtatási feladat"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> – nyomtatási feladatok"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> nyomtatási feladat</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> nyomtatási feladat</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Mégse"</string>
<string name="restart" msgid="2472034227037808749">"Újraindítás"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nincs kapcsolat a nyomtatóval"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 5936607..5babfe1 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Ավելացնել տպիչ"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Ընտրել տպիչ"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Մոռանալ տպիչը"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"Ընտրեք տպելու ծառայությունը"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Տպիչների որոնում"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Տպիչներ չեն գտնվել"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> տպման աշխատանք"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> տպման աշխատանքներ"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> տպման աշխատանք</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> տպման աշխատանք</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Չեղարկել"</string>
<string name="restart" msgid="2472034227037808749">"Վերագործարկել"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Տպիչի հետ կապ չկա"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index ab30df1..d6d505d 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Tambahkan printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Pilih printer"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Lupakan printer"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printer ditemukan</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printer ditemukan</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Pilih layanan cetak"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari printer"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Tidak ditemukan printer"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ada kesalahan printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer memblokir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tugas cetak <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tugas cetak <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Tugas cetak <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Tugas cetak <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Batal"</string>
<string name="restart" msgid="2472034227037808749">"Mulai Ulang"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tidak ada sambungan ke printer"</string>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index c6422b1..dbe05bc 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Bæta við prentara"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Veldu prentara"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Gleyma prentara"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> prentari fannst"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> prentarar fundust"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> prentari fannst</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> prentarar fundust</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Veldu prentþjónustu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Leitar að prentara"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Engir prentarar fundust"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hættir við <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Prentaravilla <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Prentari útilokaði <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> prentverk"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> prentverk"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prentverk</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prentverk</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Hætta við"</string>
<string name="restart" msgid="2472034227037808749">"Endurræsa"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Engin tenging við prentara"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index 9544ba7..ff388ca 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Aggiungi stampante"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Seleziona stampante"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Elimina stampante"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> stampante trovata"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> stampanti trovate"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> stampanti trovate</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> stampante trovata</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Scegli servizio di stampa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ricerca di stampanti"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nessuna stampante trovata"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annullamento di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errore della stampante: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La stampante ha bloccato <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Processo di stampa <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Processi di stampa <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> processi di stampa</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> processo di stampa</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Annulla"</string>
<string name="restart" msgid="2472034227037808749">"Riavvia"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nessun collegamento alla stampante"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index e3e6123..b103e2b 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"הוסף מדפסת"</string>
<string name="print_select_printer" msgid="7388760939873368698">"בחר מדפסת"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"שכח את המדפסת"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"נמצאה מדפסת <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- <item quantity="other" msgid="6533817036607128241">"נמצאו <xliff:g id="COUNT">%1$s</xliff:g> מדפסות"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="two">נמצאו <xliff:g id="COUNT_1">%1$s</xliff:g> מדפסות</item>
+ <item quantity="many">נמצאו <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_0">%1$s</xliff:g></item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"בחר שירות הדפסה"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"מחפש מדפסות"</string>
<string name="print_no_printers" msgid="4869403323900054866">"לא נמצאו מדפסות"</string>
@@ -65,10 +67,12 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"עבודת הדפסה <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> עבודות הדפסה"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="two"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="many"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one"> עבודת הדפסה <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"בטל"</string>
<string name="restart" msgid="2472034227037808749">"הפעל מחדש"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index a433d51..d782a16 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"プリンタを追加"</string>
<string name="print_select_printer" msgid="7388760939873368698">"プリンタを選択"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"プリンタを切断"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>台のプリンタが見つかりました</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>台のプリンタが見つかりました</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"印刷サービスの選択"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"プリンタの検索中"</string>
<string name="print_no_printers" msgid="4869403323900054866">"プリンタが見つかりません"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>の印刷ジョブ"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>の印刷ジョブ"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>の印刷ジョブ</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>の印刷ジョブ</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"キャンセル"</string>
<string name="restart" msgid="2472034227037808749">"再試行"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"プリンタに接続されていません"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 6edd2f3..928ab6f 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"პრინტერის დამატება"</string>
<string name="print_select_printer" msgid="7388760939873368698">"პრინტერის არჩევა"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"პრინტერის დავიწყება"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item>
- <item quantity="other" msgid="6533817036607128241">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> პრინტერი ნაპოვნია</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> პრინტერი ნაპოვნია</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"აირჩიეთ ბეჭდვის სერვისი"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"მიმდინარეობს პრინტერების ძიება"</string>
<string name="print_no_printers" msgid="4869403323900054866">"პრინტერები ვერ მოიძებნა"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"ბეჭდვის <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> დავალება"</item>
- <item quantity="other" msgid="8746611264734222865">"ბეჭდვის <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> დავალება"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ბეჭდვის დავალება</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ბეჭდვის დავალება</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"გაუქმება"</string>
<string name="restart" msgid="2472034227037808749">"გადატვირთვა"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"პრინტერთან კავშირი არ არის"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index 13dfa04..8548048 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Принтер қосу"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Принтер таңдау"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Принтерді ұмытып кету"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> принтер табылды"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> принтерлер табылды"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> принтер табылды</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> принтер табылды</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Принтер қызметін таңдау"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлерді іздеу"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Ешқандай принтер табылмады"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> басып шығару жұмысы"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> басып шығару жұмыстары"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> баспа тапсырмасы</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> баспа тапсырмасы</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Тоқтату"</string>
<string name="restart" msgid="2472034227037808749">"Қайта бастау"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтермен байланыс жоқ"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 2777b7e..b600916 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"បន្ថែមម៉ាស៊ីនបោះពុម្ព"</string>
<string name="print_select_printer" msgid="7388760939873368698">"ជ្រើសម៉ាស៊ីនបោះពុម្ព"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"ភ្លេចម៉ាស៊ីនបោះពុម្ព"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- <item quantity="other" msgid="6533817036607128241">"រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_1">%1$s</xliff:g></item>
+ <item quantity="one">រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT_0">%1$s</xliff:g></item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"ជ្រើសសេវាបោះពុម្ព"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ស្វែងរកម៉ាស៊ីនបោះពុម្ព"</string>
<string name="print_no_printers" msgid="4869403323900054866">"រកមិនឃើញម៉ាស៊ីនបោះពុម្ព"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"បោះបង់"</string>
<string name="restart" msgid="2472034227037808749">"ចាប់ផ្ដើមឡើងវិញ"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មានការភ្ជាប់ទៅម៉ាស៊ីនបោះពុម្ព"</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index 15bc98b..67b0e58 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"ಮುದ್ರಕವನ್ನು ಸೇರಿಸು"</string>
<string name="print_select_printer" msgid="7388760939873368698">"ಮುದ್ರಕವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"ಮುದ್ರಕವನ್ನು ಮರೆತುಬಿಡು"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> ಮುದ್ರಕ ಕಂಡುಬಂದಿದೆ"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> ಮುದ್ರಕಗಳು ಕಂಡುಬಂದಿವೆ"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"ಮುದ್ರಣ ಸೇವೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ಮುದ್ರಕಗಳಿಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ಯಾವುದೇ ಮುದ್ರಕಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯ"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯಗಳು"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯಗಳು</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯಗಳು</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ರದ್ದುಮಾಡು"</string>
<string name="restart" msgid="2472034227037808749">"ಮರುಪ್ರಾರಂಭಿಸು"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ಮುದ್ರಕಕ್ಕೆ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 6db4cce..7d03c44 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"프린터 추가"</string>
<string name="print_select_printer" msgid="7388760939873368698">"프린터 선택"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"프린터 삭제"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item>
- <item quantity="other" msgid="6533817036607128241">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">프린터 <xliff:g id="COUNT_1">%1$s</xliff:g>대 검색됨</item>
+ <item quantity="one">프린터 <xliff:g id="COUNT_0">%1$s</xliff:g>대 검색됨</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"인쇄 서비스 선택"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"프린터 검색 중"</string>
<string name="print_no_printers" msgid="4869403323900054866">"프린터 없음"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 인쇄 작업"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 인쇄 작업"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 인쇄 작업</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 인쇄 작업</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"취소"</string>
<string name="restart" msgid="2472034227037808749">"다시 시작"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"프린터와 연결되지 않음"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index 6a989de..9053529 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Принтер кошуу"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Принтер тандоо"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Принтерди унутуу"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> принтер табылды"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> принтер табылды"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> принтер табылды</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> принтер табылды</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Принтер кызматын тандоо"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлер изделүүдө"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Принтерлер табылган жок"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> басуу тапшырмасы"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> басуу тапшырмалары"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> басуу тапшырмасы</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> басуу тапшырмасы</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Айнуу"</string>
<string name="restart" msgid="2472034227037808749">"Кайра баштоо"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер менен байланыш жок"</string>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 20a3d80..c8aed29 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"ເພີ່ມເຄື່ອງພິມ"</string>
<string name="print_select_printer" msgid="7388760939873368698">"ເລືອກເຄື່ອງພິມ"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"ລືມເຄື່ອງພິມ"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item>
- <item quantity="other" msgid="6533817036607128241">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ເຄື່ອງພິມຖືກພົບແລ້ວ</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ເຄື່ອງພິມຖືກພົບແລ້ວ</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"ເລືອກບໍລິການການພິມ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ກຳລັງຊອກຫາເຄື່ອງພິມ"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ບໍ່ພົບເຄື່ອງພິມ"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"ງານພິມ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"ງານພິມ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ງານພິມ</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ງານພິມ</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ຍົກເລີກ"</string>
<string name="restart" msgid="2472034227037808749">"ປິດເປີດໃໝ່"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ບໍ່ມີການເຊື່ອມຕໍ່ຫາເຄື່ອງພິມ"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index 7340906..f2ca5b7 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Pridėti spausdintuvą"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Pasirinkti spausdintuvą"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Pamiršti spausdintuvą"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- <item quantity="other" msgid="6533817036607128241">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Rastas <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvas</item>
+ <item quantity="few">Rasti <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvai</item>
+ <item quantity="many">Rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvo</item>
+ <item quantity="other">Rasta <xliff:g id="COUNT_1">%1$s</xliff:g> spausdintuvų</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Pasirinkite spausdinimo paslaugą"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ieškoma spausdintuvų"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nerasta spausdintuvų"</string>
@@ -65,10 +67,12 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Atšaukiama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Spausdintuvo klaida: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Spausdintuvas užblokavo: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Spausdinimo užduotis: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Spausdinimo užduotys: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduotis</item>
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduotys</item>
+ <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduoties</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduočių</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Atšaukti"</string>
<string name="restart" msgid="2472034227037808749">"Paleisti iš naujo"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nėra ryšio su spausdintuvu"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 2fb6a1a..cc49244f 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -54,10 +54,11 @@
<string name="print_add_printer" msgid="1088656468360653455">"Pievienot printeri"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Atlasīt printeri"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Neatcerēties printeri"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Atrasts <xliff:g id="COUNT">%1$s</xliff:g> printeris"</item>
- <item quantity="other" msgid="6533817036607128241">"Atrasti <xliff:g id="COUNT">%1$s</xliff:g> printeri"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="zero">Atrasti <xliff:g id="COUNT_1">%1$s</xliff:g> printeri</item>
+ <item quantity="one">Atrasts <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
+ <item quantity="other">Atrasti <xliff:g id="COUNT_1">%1$s</xliff:g> printeri</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Izvēlieties drukāšanas pakalpojumu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printeru meklēšana"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Netika atrasts neviens printeris."</string>
@@ -65,10 +66,11 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Pārtrauc drukas darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printera kļūda ar darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeris bloķēja darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Drukas darbs <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Drukas darbi <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="zero"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbi</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbs</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbi</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Atcelt"</string>
<string name="restart" msgid="2472034227037808749">"Restartēt"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nav savienojuma ar printeri"</string>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index bf2e262..43c7c56 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Додај печатач"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Избери печатач"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Заборави го печатачот"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Пронајден е <xliff:g id="COUNT">%1$s</xliff:g> печатач"</item>
- <item quantity="other" msgid="6533817036607128241">"Пронајдени се <xliff:g id="COUNT">%1$s</xliff:g> печатачи"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"Избери услуга печатење"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пребарување печатачи"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Не се пронајдени печатачи"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Печати <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Печати <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> работа за печатење</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> работи за печатење</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Откажи"</string>
<string name="restart" msgid="2472034227037808749">"Рестартирај"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема поврзување со печатач"</string>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index 26d1788..9b577a0 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"പ്രിന്റർ ചേർക്കുക"</string>
<string name="print_select_printer" msgid="7388760939873368698">"പ്രിന്റർ തിരഞ്ഞെടുക്കുക"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"പ്രിന്റർ മറന്നു"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തി"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തി"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> പ്രിന്ററുകൾ കണ്ടെത്തി</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> പ്രിന്റർ കണ്ടെത്തി</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"പ്രിന്റ് സേവനം തിരഞ്ഞെടുക്കുക"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"പ്രിന്ററുകൾക്കായി തിരയുന്നു"</string>
<string name="print_no_printers" msgid="4869403323900054866">"പ്രിന്ററുകളൊന്നും കണ്ടെത്തിയില്ല"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> പ്രിന്റ് ജോലി"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> പ്രിന്റ് ജോലികൾ"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> പ്രിന്റ് ജോലികൾ</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> പ്രിന്റ് ജോലി</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"റദ്ദാക്കുക"</string>
<string name="restart" msgid="2472034227037808749">"പുനരാരംഭിക്കുക"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"പ്രിന്ററിൽ കണക്ഷനൊന്നുമില്ല"</string>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index 34da683..c36eacc 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Принтер нэмэх"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Принтер сонгох"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Принтерийг мартах"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> хэвлэгч олдсон байна</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> хэвлэгч олдсон байна</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Хэвлэх үйлчилгээг сонгох"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтер хайж байна"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Принтер олдсонгүй"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> хэвлэх ажил"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> хэвлэх ажлууд"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ажлыг хэвлэх</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ажлыг хэвлэх</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Цуцлах"</string>
<string name="restart" msgid="2472034227037808749">"Дахин эхлүүлэх"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер холбогдоогүй байна"</string>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index d2aa367..c79b5d3 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"प्रिंटर जोडा"</string>
<string name="print_select_printer" msgid="7388760939873368698">"प्रिंटर निवडा"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"प्रिंटर विसरा"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर आढळला"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर आढळले"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"मुद्रण सेवा निवडा"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
<string name="print_no_printers" msgid="4869403323900054866">"कोणतेही प्रिंटर आढळले नाही"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> मुद्रण कार्य"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> मुद्रण कार्ये"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> मुद्रण कार्य</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> मुद्रण कार्ये</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"रद्द करा"</string>
<string name="restart" msgid="2472034227037808749">"रीस्टार्ट करा"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटरवर कोणतेही कनेक्शन नाही"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 6b0754c..5111beb 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Tambah pencetak"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Pilih pencetak"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Lupakan pencetak"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> pencetak ditemui</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> pencetak ditemui</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Pilih perkhidmatan cetak"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari pencetak"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Tiada pencetak ditemui"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ralat pencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Pencetak disekat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Kerja cetakan <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Kerja cetakan <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Kerja cetakan <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Kerja cetakan <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Batal"</string>
<string name="restart" msgid="2472034227037808749">"Mulakan semula"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tiada sambungan ke pencetak"</string>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index c87eca1..fc0c28e 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"စာထုတ်စက်ကို ထည့်ပါ"</string>
<string name="print_select_printer" msgid="7388760939873368698">"စာထုတ်စက်ကို ရွေးရန်"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"စာထုတ်စက်ကို မေ့လိုက်ရန်"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> စာထုတ်စက် တွေ့ရှိပါသည်"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> စာထုတ်စက်များ တွေ့ရှိပါသည်"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> စာထုတ်စက်များ တွေ့ရှိပါသည်</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g>စာထုတ်စက် တွေ့ရှိပါသည်</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"စာထုတ်ရန် ဝန်ဆောင်မှုကို ရွေးချယ်ပါ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"စာထုတ်စက်များကို ရှာနေပါသည်"</string>
<string name="print_no_printers" msgid="4869403323900054866">"စာထုတ်စက် တစ်ခုမှ မတွေ့ရှိပါ"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> စာထုတ်စရာ"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> စာထုတ်စရာများ"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> စာထုတ်စရာများ</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>စာထုတ်စရာ</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ပယ်ဖျက်"</string>
<string name="restart" msgid="2472034227037808749">"အစက ပြန်စရန်"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 441444e..390a3d7 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Legg til skriver"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Velg skriver"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Glem skriveren"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skriver ble funnet"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivere ble funnet"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> skrivere ble funnet</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> skriver ble funnet</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Velg utskriftstjeneste"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søker etter skrivere"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Fant ingen skrivere"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skriverfeil <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Skriveren blokkerte <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Utskriftsjobb for <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Utskriftsjobber for <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> utskriftsjobber</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> utskriftsjobb</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Avbryt"</string>
<string name="restart" msgid="2472034227037808749">"Start på nytt"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse med skriveren"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index dd20bbb..7c4ecb0 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"प्रिन्टर थप्नुहोस्"</string>
<string name="print_select_printer" msgid="7388760939873368698">"प्रिन्टर चयन गर्नुहोस्"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"प्रिन्टर बिर्सनुहोस्"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिन्टर भेटाइयो"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिन्टरहरू भेटाइयो"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> प्रिन्टरहरू भेटिए</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> प्रिन्टर भेटियो</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"प्रिन्ट सेवा छनौट गर्नुहोस्"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिन्टरहरू खोज्दै"</string>
<string name="print_no_printers" msgid="4869403323900054866">"कुनै प्रिन्टरहरू भेटाइएन"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> प्रिन्ट कार्य"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> प्रिन्ट कार्यहरु"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> कार्यहरू प्रिन्ट गर्नुहोस्</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> कार्य प्रिन्ट गर्नुहोस्</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"रद्द गर्नुहोस्"</string>
<string name="restart" msgid="2472034227037808749">"पुनःस्टार्ट गर्नुहोस्"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिन्टरमा कुनै जडान छैन"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 31c0110..44ec72c 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Printer toevoegen"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Printer selecteren"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Printer vergeten"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer gevonden"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers gevonden"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> printers gevonden</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> printer gevonden</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Afdrukservice kiezen"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printers zoeken"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Geen printers gevonden"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annuleren"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerfout <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> geblokkeerd door printer"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> afdruktaak"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> afdruktaken"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> afdruktaken</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> afdruktaak</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuleren"</string>
<string name="restart" msgid="2472034227037808749">"Opnieuw starten"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met printer"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index ccba0d5..0365e1d 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Dodaj drukarkę"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Wybierz drukarkę"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Nie zapamiętuj drukarki"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Znaleziono <xliff:g id="COUNT">%1$s</xliff:g> drukarkę"</item>
- <item quantity="other" msgid="6533817036607128241">"Znalezione drukarki: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="few">Znaleziono <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+ <item quantity="many">Znaleziono <xliff:g id="COUNT_1">%1$s</xliff:g> drukarek</item>
+ <item quantity="other">Znaleziono <xliff:g id="COUNT_1">%1$s</xliff:g> drukarki</item>
+ <item quantity="one">Znaleziono <xliff:g id="COUNT_0">%1$s</xliff:g> drukarkę</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Wybierz usługę drukowania"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Szukanie drukarek"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nie znaleziono drukarek"</string>
@@ -65,10 +67,12 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Anulowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Błąd drukarki: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drukarka zablokowała <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> zadanie drukowania"</item>
- <item quantity="other" msgid="8746611264734222865">"Zadania drukowania: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadania drukowania</item>
+ <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadań drukowania</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadania drukowania</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> zadanie drukowania</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Anuluj"</string>
<string name="restart" msgid="2472034227037808749">"Od nowa"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Brak połączenia z drukarką"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 5efa1d7..9f6ccdb 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Escolher o serviço de impressão"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"A procurar impressoras"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nenhuma impressora encontrada"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impressora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tarefa de impressão: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tarefas de impressão: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tarefas de impressão</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tarefa de impressão</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem ligação à impressora"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 52875dd..31a24ea 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Selecione o serviço de impressão"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nenhuma impressora encontrada"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impressora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Trabalho de impressão <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Trabalhos de impressão <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem conexão com a impressora"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 98d3761..efcfc75 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -54,10 +54,11 @@
<string name="print_add_printer" msgid="1088656468360653455">"Adăugați o imprimantă"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Selectați imprimanta"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Omiteți imprimanta"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantă găsită"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (de) imprimante găsite"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="few"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante găsite</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> de imprimante găsite</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> imprimantă găsită</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Alegeți serviciul de printare"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Se caută imprimante"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nu au fost găsite imprimante"</string>
@@ -65,10 +66,11 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Se anulează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Eroare de printare: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printare blocată: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Sarcină de printare <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Sarcini de printare <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> activități de printare</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> de activități de printare</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> activitate de printare</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Anulați"</string>
<string name="restart" msgid="2472034227037808749">"Reporniți"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nu există conexiune la o imprimantă"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 4d9861a..4c8dfdc 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Добавить принтер"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Выбрать принтер"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Удалить принтер"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Найден <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item>
- <item quantity="other" msgid="6533817036607128241">"Найдено принтеров: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Найден <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+ <item quantity="few">Найдено <xliff:g id="COUNT_1">%1$s</xliff:g> принтера</item>
+ <item quantity="many">Найдено <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="choose_print_service" msgid="3740309762324459694">"Выберите службу печати"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Поиск принтеров…"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Ничего не найдено"</string>
@@ -65,10 +67,12 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Задание печати: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Задания печати: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="few">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="many">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Отмена"</string>
<string name="restart" msgid="2472034227037808749">"Повторить"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нет связи с принтером"</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index dae8a02..855dcd1 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"මුද්රණ යන්ත්ර එකතු කරන්න"</string>
<string name="print_select_printer" msgid="7388760939873368698">"මුද්රකය තේරීම"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"මුද්රකය අමතක කිරීම"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"මුද්රණ යන්ත්ර <xliff:g id="COUNT">%1$s</xliff:g> ක් සොයා ගැනිණි"</item>
- <item quantity="other" msgid="6533817036607128241">"මුද්රණ යන්ත්ර <xliff:g id="COUNT">%1$s</xliff:g> ක් සොයා ගැනිණි"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <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="choose_print_service" msgid="3740309762324459694">"මුද්රණ සේවාව තෝරන්න"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"මුද්රණ යන්ත්ර සොයමින්"</string>
<string name="print_no_printers" msgid="4869403323900054866">"මුද්රණ යන්ත්ර සොයා නොගැනුණි"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> මුද්රණ කාර්යය"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> මුද්රණ කාර්යයන්"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one">මුද්රණ කාර්ය <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">මුද්රණ කාර්ය <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"අවලංගු කරන්න"</string>
<string name="restart" msgid="2472034227037808749">"යළි අරඹන්න"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"මුද්රණ යන්ත්රය වෙත සම්බන්ධය නැත"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index ecb70b8..a5ff4a9 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Pridať tlačiareň"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Vybrať tlačiareň"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Odstrániť tlačiareň"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Našla sa <xliff:g id="COUNT">%1$s</xliff:g> tlačiareň"</item>
- <item quantity="other" msgid="6533817036607128241">"Počet nájdených tlačiarní: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="few">Našli sa <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+ <item quantity="many">Našlo sa <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarne</item>
+ <item quantity="other">Našlo sa <xliff:g id="COUNT_1">%1$s</xliff:g> tlačiarní</item>
+ <item quantity="one">Našla sa <xliff:g id="COUNT_0">%1$s</xliff:g> tlačiareň</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Výber tlačovej služby"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhľadávanie tlačiarní"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nenašli sa žiadne tlačiarne"</string>
@@ -65,10 +67,12 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prebieha zrušenie úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tlačiarne – úloha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tlačiareň zablok. úlohu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Počet tlačových úloh: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Počet tlačových úloh: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačové úlohy</item>
+ <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačovej úlohy</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačových úloh</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tlačová úloha</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Zrušiť"</string>
<string name="restart" msgid="2472034227037808749">"Spustiť znova"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Žiadne pripojenie k tlačiarni"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index c94429e..e6d7358 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Dodajanje tiskalnika"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Izbira tiskalnika"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Odstranitev tiskalnika"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Najden <xliff:g id="COUNT">%1$s</xliff:g> tiskalnik"</item>
- <item quantity="other" msgid="6533817036607128241">"Število najdenih tiskalnikov: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> najden tiskalnik</item>
+ <item quantity="two"><xliff:g id="COUNT_1">%1$s</xliff:g> najdena tiskalnika</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$s</xliff:g> najdeni tiskalniki</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> najdenih tiskalnikov</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Izberite tiskalno storitev"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Iskanje tiskalnikov"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Tiskalnikov ni mogoče najti"</string>
@@ -65,10 +67,12 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Preklic: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Napaka tiskalnika: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tiskalnik je blokiral <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Tiskalno opravilo: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Tiskalna opravila: <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalno opravilo</item>
+ <item quantity="two"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalni opravili</item>
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalna opravila</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalnih opravil</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Prekliči"</string>
<string name="restart" msgid="2472034227037808749">"Začni znova"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ni povezave s tiskalnikom"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 7bc912c..677d5e1 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -54,10 +54,11 @@
<string name="print_add_printer" msgid="1088656468360653455">"Додај штампач"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Изабери штампач"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Заборави штампач"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Пронађен је <xliff:g id="COUNT">%1$s</xliff:g> штампач"</item>
- <item quantity="other" msgid="6533817036607128241">"Пронађено је <xliff:g id="COUNT">%1$s</xliff:g> штампача"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Пронађен је <xliff:g id="COUNT_1">%1$s</xliff:g> штампач</item>
+ <item quantity="few">Пронађена су <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="choose_print_service" msgid="3740309762324459694">"Изаберите услугу штампања"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Претрага штампача"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Није пронађен ниједан штампач"</string>
@@ -65,10 +66,11 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Задатак штампања <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Задаци штампања <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="few">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="other">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Откажи"</string>
<string name="restart" msgid="2472034227037808749">"Поново покрени"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема везе са штампачем"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index c46d4df..cda72e2 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Lägg till skrivare"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Välj en skrivare"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Ta bort en skrivare"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> skrivare hittades</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> skrivare hittades</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Välj utskriftstjänst"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Söker efter skrivare"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Det gick inte att hitta några skrivare"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skrivarfel för <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Skrivaren har blockerat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Utskriftsjobb – <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Utskriftsjobb – <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> utskriftsjobb</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> utskriftsjobb</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Avbryt"</string>
<string name="restart" msgid="2472034227037808749">"Starta om"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen anslutning till skrivaren"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 9c808be..d784ab6 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Ongeza printa"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Chagua printa"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Sahau printa"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Printa <xliff:g id="COUNT">%1$s</xliff:g> imepatikana"</item>
- <item quantity="other" msgid="6533817036607128241">"Printa <xliff:g id="COUNT">%1$s</xliff:g> zimepatikana"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Printa <xliff:g id="COUNT_1">%1$s</xliff:g> zimepatikana</item>
+ <item quantity="one">Printa <xliff:g id="COUNT_0">%1$s</xliff:g> imepatikana</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Chagua huduma ya printa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inatafuta printa"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Hakuna printa zilizopatikana"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Inaghairi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Hitilafu ya kuchapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printa imefungwa <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Kazi ya kuchapisha ya <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Kazi za kuchapisha za <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Kazi ya kuchapisha ya <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Kazi ya kuchapisha ya <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> </item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Ghairi"</string>
<string name="restart" msgid="2472034227037808749">"Anzisha upya"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 1395d29..6f29851 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"பிரிண்டரைச் சேர்"</string>
<string name="print_select_printer" msgid="7388760939873368698">"பிரிண்டரைத் தேர்ந்தெடுக்கவும்"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"பிரிண்டரை நீக்கு"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> பிரிண்டர் உள்ளது"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> பிரிண்டர்கள் உள்ளன"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> பிரிண்டர்கள் உள்ளன</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> பிரிண்டர் உள்ளது</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"அச்சுப் பொறியைத் தேர்வுசெய்யவும்"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"அச்சுப்பொறிகளைத் தேடுகிறது"</string>
<string name="print_no_printers" msgid="4869403323900054866">"பிரிண்டர்கள் எதுவுமில்லை"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> அச்சுப் பணி"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> அச்சுப் பணிகள்"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> அச்சுப் பணிகள்</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> அச்சுப் பணி</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ரத்துசெய்"</string>
<string name="restart" msgid="2472034227037808749">"மீண்டும் தொடங்கு"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"அச்சுப்பொறியுடன் இணைக்கப்படவில்லை"</string>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index 9958f05..88c83da 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"ప్రింటర్ను జోడించు"</string>
<string name="print_select_printer" msgid="7388760939873368698">"ప్రింటర్ను ఎంచుకోండి"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"ప్రింటర్ను విస్మరించు"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> ప్రింటర్ కనుగొనబడింది"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> ప్రింటర్లు కనుగొనబడ్డాయి"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ప్రింటర్లు కనుగొనబడ్డాయి</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ప్రింటర్ కనుగొనబడింది</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"ముద్రణ సేవను ఎంచుకోండి"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ప్రింటర్ల కోసం శోధిస్తోంది"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ప్రింటర్లు కనుగొనబడలేదు"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> ముద్రణ జాబ్"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> ముద్రణ జాబ్లు"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ముద్రణ జాబ్లు</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ముద్రణ జాబ్</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"రద్దు చేయి"</string>
<string name="restart" msgid="2472034227037808749">"పునఃప్రారంభించు"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ప్రింటర్కు కనెక్షన్ లేదు"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index cef716a..7731a7d 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"เพิ่มเครื่องพิมพ์"</string>
<string name="print_select_printer" msgid="7388760939873368698">"เลือกเครื่องพิมพ์"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"ไม่ต้องจำเครื่องพิมพ์"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item>
- <item quantity="other" msgid="6533817036607128241">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">พบเครื่องพิมพ์ <xliff:g id="COUNT_1">%1$s</xliff:g> เครื่อง</item>
+ <item quantity="one">พบเครื่องพิมพ์ <xliff:g id="COUNT_0">%1$s</xliff:g> เครื่อง</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"เลือกบริการพิมพ์"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"กำลังค้นหาเครื่องพิมพ์"</string>
<string name="print_no_printers" msgid="4869403323900054866">"ไม่พบเครื่องพิมพ์"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"งานพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"งานพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> งานพิมพ์</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> งานพิมพ์</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"ยกเลิก"</string>
<string name="restart" msgid="2472034227037808749">"เริ่มต้นใหม่"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ไม่มีการเชื่อมต่อไปยังเครื่องพิมพ์"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 58e1930..b4bda0c 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Magdagdag ng printer"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Piliin ang printer"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Kalimutan ang printer"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ang nakita"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (na) printer ang nakita"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> nakitang printer</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> na nakitang printer</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Pumili ng serbisyo ng pag-print"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Naghahanap ng mga printer"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Walang mga printer na nakita"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kinakansela ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error sa printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Naka-block ang Printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Pag-print ng <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Mga pag-print ng <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ipi-print</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> na ipi-print</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Kanselahin"</string>
<string name="restart" msgid="2472034227037808749">"I-restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hindi nakakonekta sa printer"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index 39b5c9a..9fa7d8e 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Yazıcı ekle"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Yazıcı seç"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Yazıcıyı unut"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> yazıcı bulundu</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> yazıcı bulundu</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Yazdırma hizmetini seçin"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Yazıcılar aranıyor"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Yazıcı bulunamadı"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> iptal ediliyor"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Yazıcı hatası: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Yazıcı <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> işini engelledi"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> yazdırma işi"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> yazdırma işleri"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> yazdırma işi</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> yazdırma işi</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"İptal"</string>
<string name="restart" msgid="2472034227037808749">"Yeniden başlat"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Yazıcı bağlantısı yok"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 73030e4..0b283b9 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -54,10 +54,12 @@
<string name="print_add_printer" msgid="1088656468360653455">"Додати принтер"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Вибрати принтер"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Ігнорувати принтер"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- <item quantity="other" msgid="6533817036607128241">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one">Знайдено <xliff:g id="COUNT_1">%1$s</xliff:g> принтер</item>
+ <item quantity="few">Знайдено <xliff:g id="COUNT_1">%1$s</xliff:g> принтери</item>
+ <item quantity="many">Знайдено <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="choose_print_service" msgid="3740309762324459694">"Вибрати службу друку"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пошук принтерів"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Принтери не знайдено"</string>
@@ -65,10 +67,12 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Завдання друку <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Завдання друку <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдання друку</item>
+ <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдання друку</item>
+ <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдань друку</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдань друку</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Скасувати"</string>
<string name="restart" msgid="2472034227037808749">"Перезапустити"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Немає з’єднання з принтером"</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 5c9f471..2b138c1 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"پرنٹر شامل کریں"</string>
<string name="print_select_printer" msgid="7388760939873368698">"پرنٹر منتخب کریں"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"پرنٹر کو بھول جائیں"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> پرنٹر ملا"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> پرنٹرز ملے"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> پرنٹرز ملے</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> پرنٹر ملا</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"پرنٹ سروس منتخب کریں"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"پرنٹرز تلاش کر رہا ہے"</string>
<string name="print_no_printers" msgid="4869403323900054866">"کوئی پرنٹرز نہيں ملے"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> پرنٹ جاب"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> پرنٹ جابز"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> پرنٹ جابز</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> پرنٹ جاب</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"منسوخ کریں"</string>
<string name="restart" msgid="2472034227037808749">"دوبارہ شروع کریں"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"پرنٹر کے ساتھ کوئی کنکشن نہیں ہے"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index 40b7109..26b5c9f 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Printer qo‘shish"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Printerni tanlang"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Printerni unutish"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g>ta printer topildi"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g>ta printer topildi"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> ta printer topildi</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> ta printer topildi</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Chop etish xizmatini tanlang"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlarni izlash"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Printerlar topilmadi"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bekor qilinmoqda"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerda xatolik: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ni taqiqladi"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> chop etish buyrug‘i"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> chop etish buyruqlari"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> chop qilish vazifalari</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> chop qilish vazifasi</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Bekor qilish"</string>
<string name="restart" msgid="2472034227037808749">"Qayta boshlash"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printer ulanmagan"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index c61c1fa..d6ef07c 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Thêm máy in"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Chọn máy in"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Bỏ qua máy in"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item>
- <item quantity="other" msgid="6533817036607128241">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">Đã tìm thấy <xliff:g id="COUNT_1">%1$s</xliff:g> máy in</item>
+ <item quantity="one">Đã tìm thấy <xliff:g id="COUNT_0">%1$s</xliff:g> máy in</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Chọn dịch vụ in"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Đang tìm kiếm máy in"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Không tìm thấy máy in"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hủy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Lỗi máy in <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Máy in đã chặn <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"Lệnh in <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- <item quantity="other" msgid="8746611264734222865">"Lệnh in <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">Lệnh in <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
+ <item quantity="one">Lệnh in <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Hủy"</string>
<string name="restart" msgid="2472034227037808749">"Bắt đầu lại"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Không có kết nối nào với máy in"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 3eb1b63..b6ab6b5 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"添加打印机"</string>
<string name="print_select_printer" msgid="7388760939873368698">"选择打印机"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"取消保存打印机"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item>
- <item quantity="other" msgid="6533817036607128241">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">找到 <xliff:g id="COUNT_1">%1$s</xliff:g> 台打印机</item>
+ <item quantity="one">找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 台打印机</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"选择打印服务"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
<string name="print_no_printers" msgid="4869403323900054866">"找不到打印机"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"“<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>”打印作业"</item>
- <item quantity="other" msgid="8746611264734222865">"“<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g>”打印作业"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other">“<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>”打印作业</item>
+ <item quantity="one">“<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>”打印作业</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新开始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"未与打印机建立连接"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 88c6961..8f8bf13a 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"新增打印機"</string>
<string name="print_select_printer" msgid="7388760939873368698">"選取打印機"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"移除打印機"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item>
- <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">已找到 <xliff:g id="COUNT_1">%1$s</xliff:g> 部打印機</item>
+ <item quantity="one">已找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 部打印機</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋打印機"</string>
<string name="print_no_printers" msgid="4869403323900054866">"找不到打印機"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"一項 <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 列印工作"</item>
- <item quantity="other" msgid="8746611264734222865">"多項 <xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 列印工作"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 項列印工作</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 項列印工作</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新開始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與打印機連線"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 2d8631c..7872d24 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"新增印表機"</string>
<string name="print_select_printer" msgid="7388760939873368698">"選取印表機"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"移除印表機"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item>
- <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="other">找到 <xliff:g id="COUNT_1">%1$s</xliff:g> 台印表機</item>
+ <item quantity="one">找到 <xliff:g id="COUNT_0">%1$s</xliff:g> 台印表機</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋印表機"</string>
<string name="print_no_printers" msgid="4869403323900054866">"找不到印表機"</string>
@@ -65,10 +65,10 @@
<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>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 個列印工作"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> 個列印工作"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 個列印工作</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 個列印工作</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新開始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與印表機建立連線"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index d3ee17c..ddb953b 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -54,10 +54,10 @@
<string name="print_add_printer" msgid="1088656468360653455">"Engeza iphrinta"</string>
<string name="print_select_printer" msgid="7388760939873368698">"Khetha iphrinta"</string>
<string name="print_forget_printer" msgid="5035287497291910766">"Khohlwa iphrinta"</string>
- <plurals name="print_search_result_count_utterance">
- <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> iphrinta itholiwe"</item>
- <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> amaphrinta atholiwe"</item>
- </plurals>
+ <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> amaphrinta atholakele</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> amaphrinta atholakele</item>
+ </plurals>
<string name="choose_print_service" msgid="3740309762324459694">"Khetha isevisi yephrinta"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Isesha amaphrinta"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Awekho amaphrinta atholiwe"</string>
@@ -65,10 +65,10 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ikhansela i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Iphutha lephrinta ye-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Iphrinta engu-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ivinjelwe"</string>
- <plurals name="composite_notification_title_template">
- <item quantity="one" msgid="5866624638054847057">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> umsebenzi wokuphrinta"</item>
- <item quantity="other" msgid="8746611264734222865">"<xliff:g id="PRINT_JOB_NAME">%1$d</xliff:g> imisebenzi yokuphrinta"</item>
- </plurals>
+ <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> imisebenzi yokuphrinta</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> imisebenzi yokuphrinta</item>
+ </plurals>
<string name="cancel" msgid="4373674107267141885">"Khansela"</string>
<string name="restart" msgid="2472034227037808749">"Qala kabusha"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Akukho ukuxhumana kuphrinta"</string>
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..6e29d23
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png
new file mode 100644
index 0000000..6110e9e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headphones_a2dp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png
new file mode 100644
index 0000000..6cca225
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_headset_hfp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png
new file mode 100644
index 0000000..6445f2a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_misc_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png
new file mode 100644
index 0000000..78c0294
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_network_pan.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png
new file mode 100644
index 0000000..2fcc3b0
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_bt_pointing_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..70d35bf
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-hdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..2d9b75e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-ldrtl-hdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..b6ebe34
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-ldrtl-mdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..8b67b91
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-ldrtl-xhdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..1fa0a3d
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png
new file mode 100644
index 0000000..175bd78
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headphones_a2dp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png
new file mode 100644
index 0000000..05b27e8
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_headset_hfp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png
new file mode 100644
index 0000000..6e9f8ae
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_misc_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png
new file mode 100644
index 0000000..5f3371f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_network_pan.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png
new file mode 100644
index 0000000..539d77f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_bt_pointing_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..3216776
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-mdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..4f381ba
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png
new file mode 100644
index 0000000..c67127d
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headphones_a2dp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png
new file mode 100644
index 0000000..d3b356b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_headset_hfp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png
new file mode 100644
index 0000000..2d38129
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_misc_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png
new file mode 100644
index 0000000..fb76575
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_network_pan.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png
new file mode 100644
index 0000000..d8b68eb
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_bt_pointing_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..02cc3af
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xhdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..7805b7a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png
new file mode 100644
index 0000000..8127774
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headphones_a2dp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png
new file mode 100644
index 0000000..84b8085
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_headset_hfp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png
new file mode 100644
index 0000000..289d6ac
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_misc_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png
new file mode 100644
index 0000000..72bc804
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_network_pan.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png
new file mode 100644
index 0000000..e31ce2b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_bt_pointing_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..f23b0e7
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxhdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png
new file mode 100644
index 0000000..1e12f96
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_cellphone.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png
new file mode 100644
index 0000000..8b547d9
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headphones_a2dp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png
new file mode 100644
index 0000000..03c5033
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_headset_hfp.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png
new file mode 100644
index 0000000..b9a9923
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_misc_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png
new file mode 100644
index 0000000..989e1ab
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_network_pan.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png
new file mode 100644
index 0000000..de8c389
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_bt_pointing_hid.png
Binary files differ
diff --git a/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png b/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png
new file mode 100644
index 0000000..2eb8a92
--- /dev/null
+++ b/packages/SettingsLib/res/drawable-xxxhdpi/ic_lockscreen_ime.png
Binary files differ
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f055a2c..870afeb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -67,4 +67,87 @@
<!-- Status message of Wi-Fi when it is connected by a Wi-Fi assistant application. [CHAR LIMIT=NONE] -->
<string name="connected_via_wfa">Connected via Wi\u2011Fi assistant</string>
+
+ <!-- Bluetooth settings. Message when a device is disconnected -->
+ <string name="bluetooth_disconnected">Disconnected</string>
+ <!-- Bluetooth settings. Message when disconnecting from a device -->
+ <string name="bluetooth_disconnecting">Disconnecting\u2026</string>
+ <!-- Bluetooth settings. Message when connecting to a device -->
+ <string name="bluetooth_connecting">Connecting\u2026</string>
+ <!-- Bluetooth settings. Message when connected to a device. [CHAR LIMIT=40] -->
+ <string name="bluetooth_connected">Connected</string>
+
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the A2DP profile. -->
+ <string name="bluetooth_profile_a2dp">Media audio</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the headset or handsfree profile. -->
+ <string name="bluetooth_profile_headset">Phone audio</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the OPP profile. -->
+ <string name="bluetooth_profile_opp">File transfer</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the HID profile. -->
+ <string name="bluetooth_profile_hid">Input device</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (accessing Internet through remote device). [CHAR LIMIT=40] -->
+ <string name="bluetooth_profile_pan">Internet access</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PBAP profile. [CHAR LIMIT=40] -->
+ <string name="bluetooth_profile_pbap">Contact sharing</string>
+ <!-- Bluetooth settings. The user-visible summary string that is used whenever referring to the PBAP profile (sharing contacts). [CHAR LIMIT=60] -->
+ <string name="bluetooth_profile_pbap_summary">Use for contact sharing</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (sharing this device's Internet connection). [CHAR LIMIT=40] -->
+ <string name="bluetooth_profile_pan_nap">Internet connection sharing</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the map profile. -->
+ <string name="bluetooth_profile_map">Message Access</string>
+
+ <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. -->
+ <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the headset checkbox preference when headset is connected. -->
+ <string name="bluetooth_headset_profile_summary_connected">Connected to phone audio</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference when OPP is connected. -->
+ <string name="bluetooth_opp_profile_summary_connected">Connected to file transfer server</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference when map is connected. -->
+ <string name="bluetooth_map_profile_summary_connected">Connected to map</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference when OPP is not connected. -->
+ <string name="bluetooth_opp_profile_summary_not_connected">Not connected to file transfer server</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the HID checkbox preference when HID is connected. -->
+ <string name="bluetooth_hid_profile_summary_connected">Connected to input device</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the checkbox preference when PAN is connected (user role). [CHAR LIMIT=25]-->
+ <string name="bluetooth_pan_user_profile_summary_connected">Connected to device for Internet access</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the checkbox preference when PAN is connected (NAP role). [CHAR LIMIT=25]-->
+ <string name="bluetooth_pan_nap_profile_summary_connected">Sharing local Internet connection with device</string>
+
+ <!-- Bluetooth settings. Connection options screen. The summary
+ for the PAN checkbox preference that describes how checking it
+ will set the PAN profile as preferred. -->
+ <string name="bluetooth_pan_profile_summary_use_for">Use for Internet access</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference that describes how checking it will set the map profile as preferred. -->
+ <string name="bluetooth_map_profile_summary_use_for">Use for map</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference that describes how checking it will set the A2DP profile as preferred. -->
+ <string name="bluetooth_a2dp_profile_summary_use_for">Use for media audio</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the headset checkbox preference that describes how checking it will set the headset profile as preferred. -->
+ <string name="bluetooth_headset_profile_summary_use_for">Use for phone audio</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference that describes how checking it will set the OPP profile as preferred. -->
+ <string name="bluetooth_opp_profile_summary_use_for">Use for file transfer</string>
+ <!-- Bluetooth settings. Connection options screen. The summary
+ for the HID checkbox preference that describes how checking it
+ will set the HID profile as preferred. -->
+ <string name="bluetooth_hid_profile_summary_use_for">Use for input</string>
+
+ <!-- Button text for accepting an incoming pairing request. [CHAR LIMIT=20] -->
+ <string name="bluetooth_pairing_accept">Pair</string>
+ <!-- Button text for accepting an incoming pairing request in all caps. [CHAR LIMIT=20] -->
+ <string name="bluetooth_pairing_accept_all_caps">PAIR</string>
+ <!-- Button text for declining an incoming pairing request. [CHAR LIMIT=20] -->
+ <string name="bluetooth_pairing_decline">Cancel</string>
+
+ <!-- Message in pairing dialogs. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_pairing_will_share_phonebook">Pairing grants access to your contacts and call history when connected.</string>
+ <!-- Message for the error dialog when BT pairing fails generically. -->
+ <string name="bluetooth_pairing_error_message">Couldn\'t pair with <xliff:g id="device_name">%1$s</xliff:g>.</string>
+
+ <!-- Message for the error dialog when BT pairing fails because the PIN /
+ Passkey entered is incorrect. -->
+ <string name="bluetooth_pairing_pin_error_message">Couldn\'t pair with <xliff:g id="device_name">%1$s</xliff:g> because of an incorrect PIN or passkey.</string>
+ <!-- Message for the error dialog when BT pairing fails because the other device is down. -->
+ <string name="bluetooth_pairing_device_down_error_message">Can\'t communicate with <xliff:g id="device_name">%1$s</xliff:g>.</string>
+ <!-- Message for the error dialog when BT pairing fails because the other device rejected the pairing. -->
+ <string name="bluetooth_pairing_rejected_error_message">Pairing rejected by <xliff:g id="device_name">%1$s</xliff:g>.</string>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
new file mode 100644
index 0000000..58e5e29a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+public class TetherUtil {
+
+ // Types of tethering.
+ public static final int TETHERING_INVALID = -1;
+ public static final int TETHERING_WIFI = 0;
+ public static final int TETHERING_USB = 1;
+ public static final int TETHERING_BLUETOOTH = 2;
+
+ // Extras used for communicating with the TetherService.
+ public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+ public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+ public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+ /**
+ * Tells the service to run a provision check now.
+ */
+ public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+ /**
+ * Enables wifi tethering if the provision check is successful. Used by
+ * QS to enable tethering.
+ */
+ public static final String EXTRA_ENABLE_WIFI_TETHER = "extraEnableWifiTether";
+
+ public static ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
+ .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
+
+ public static boolean setWifiTethering(boolean enable, Context context) {
+ final WifiManager wifiManager =
+ (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ final ContentResolver cr = context.getContentResolver();
+ /**
+ * Disable Wifi if enabling tethering
+ */
+ int wifiState = wifiManager.getWifiState();
+ if (enable && ((wifiState == WifiManager.WIFI_STATE_ENABLING) ||
+ (wifiState == WifiManager.WIFI_STATE_ENABLED))) {
+ wifiManager.setWifiEnabled(false);
+ Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1);
+ }
+
+ boolean success = wifiManager.setWifiApEnabled(null, enable);
+ /**
+ * If needed, restore Wifi on tether disable
+ */
+ if (!enable) {
+ int wifiSavedState = Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
+ if (wifiSavedState == 1) {
+ wifiManager.setWifiEnabled(true);
+ Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
+ }
+ }
+ return success;
+ }
+
+ public static boolean isWifiTetherEnabled(Context context) {
+ WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ return wifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED;
+ }
+
+ public static boolean isProvisioningNeeded(Context context) {
+ // Keep in sync with other usage of config_mobile_hotspot_provision_app.
+ // ConnectivityManager#enforceTetherChangePermission
+ String[] provisionApp = context.getResources().getStringArray(
+ com.android.internal.R.array.config_mobile_hotspot_provision_app);
+ if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
+ || provisionApp == null) {
+ return false;
+ }
+ return (provisionApp.length == 2);
+ }
+
+ public static boolean isTetheringSupported(Context context) {
+ final ConnectivityManager cm =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ final boolean isSecondaryUser = ActivityManager.getCurrentUser() != UserHandle.USER_OWNER;
+ return !isSecondaryUser && cm.isTetheringSupported();
+ }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
new file mode 100755
index 0000000..9608daa
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class A2dpProfile implements LocalBluetoothProfile {
+ private static final String TAG = "A2dpProfile";
+ private static boolean V = false;
+
+ private BluetoothA2dp mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+
+ static final ParcelUuid[] SINK_UUIDS = {
+ BluetoothUuid.AudioSink,
+ BluetoothUuid.AdvAudioDist,
+ };
+
+ static final String NAME = "A2DP";
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 1;
+
+ // These callbacks run on the main thread.
+ private final class A2dpServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothA2dp) proxy;
+ // We just bound to the service, so refresh the UI for any connected A2DP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "A2dpProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(A2dpProfile.this, BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ A2dpProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(),
+ BluetoothProfile.A2DP);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> sinks = getConnectedDevices();
+ if (sinks != null) {
+ for (BluetoothDevice sink : sinks) {
+ mService.disconnect(sink);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ // Downgrade priority as user is disconnecting the headset.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+ boolean isA2dpPlaying() {
+ if (mService == null) return false;
+ List<BluetoothDevice> sinks = mService.getConnectedDevices();
+ if (!sinks.isEmpty()) {
+ if (mService.isA2dpPlaying(sinks.get(0))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_a2dp;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_a2dp_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_a2dp_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_headphones_a2dp;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up A2DP proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
new file mode 100644
index 0000000..b802f58
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+
+/**
+ * BluetoothCallback provides a callback interface for the settings
+ * UI to receive events from {@link BluetoothEventManager}.
+ */
+public interface BluetoothCallback {
+ void onBluetoothStateChanged(int bluetoothState);
+ void onScanningStateChanged(boolean started);
+ void onDeviceAdded(CachedBluetoothDevice cachedDevice);
+ void onDeviceDeleted(CachedBluetoothDevice cachedDevice);
+ void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
new file mode 100644
index 0000000..8dec86a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothUuid;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+/**
+ * BluetoothDeviceFilter contains a static method that returns a
+ * Filter object that returns whether or not the BluetoothDevice
+ * passed to it matches the specified filter type constant from
+ * {@link android.bluetooth.BluetoothDevicePicker}.
+ */
+public final class BluetoothDeviceFilter {
+ private static final String TAG = "BluetoothDeviceFilter";
+
+ /** The filter interface to external classes. */
+ public interface Filter {
+ boolean matches(BluetoothDevice device);
+ }
+
+ /** All filter singleton (referenced directly). */
+ public static final Filter ALL_FILTER = new AllFilter();
+
+ /** Bonded devices only filter (referenced directly). */
+ public static final Filter BONDED_DEVICE_FILTER = new BondedDeviceFilter();
+
+ /** Unbonded devices only filter (referenced directly). */
+ public static final Filter UNBONDED_DEVICE_FILTER = new UnbondedDeviceFilter();
+
+ /** Table of singleton filter objects. */
+ private static final Filter[] FILTERS = {
+ ALL_FILTER, // FILTER_TYPE_ALL
+ new AudioFilter(), // FILTER_TYPE_AUDIO
+ new TransferFilter(), // FILTER_TYPE_TRANSFER
+ new PanuFilter(), // FILTER_TYPE_PANU
+ new NapFilter() // FILTER_TYPE_NAP
+ };
+
+ /** Private constructor. */
+ private BluetoothDeviceFilter() {
+ }
+
+ /**
+ * Returns the singleton {@link Filter} object for the specified type,
+ * or {@link #ALL_FILTER} if the type value is out of range.
+ *
+ * @param filterType a constant from BluetoothDevicePicker
+ * @return a singleton object implementing the {@link Filter} interface.
+ */
+ public static Filter getFilter(int filterType) {
+ if (filterType >= 0 && filterType < FILTERS.length) {
+ return FILTERS[filterType];
+ } else {
+ Log.w(TAG, "Invalid filter type " + filterType + " for device picker");
+ return ALL_FILTER;
+ }
+ }
+
+ /** Filter that matches all devices. */
+ private static final class AllFilter implements Filter {
+ public boolean matches(BluetoothDevice device) {
+ return true;
+ }
+ }
+
+ /** Filter that matches only bonded devices. */
+ private static final class BondedDeviceFilter implements Filter {
+ public boolean matches(BluetoothDevice device) {
+ return device.getBondState() == BluetoothDevice.BOND_BONDED;
+ }
+ }
+
+ /** Filter that matches only unbonded devices. */
+ private static final class UnbondedDeviceFilter implements Filter {
+ public boolean matches(BluetoothDevice device) {
+ return device.getBondState() != BluetoothDevice.BOND_BONDED;
+ }
+ }
+
+ /** Parent class of filters based on UUID and/or Bluetooth class. */
+ private abstract static class ClassUuidFilter implements Filter {
+ abstract boolean matches(ParcelUuid[] uuids, BluetoothClass btClass);
+
+ public boolean matches(BluetoothDevice device) {
+ return matches(device.getUuids(), device.getBluetoothClass());
+ }
+ }
+
+ /** Filter that matches devices that support AUDIO profiles. */
+ private static final class AudioFilter extends ClassUuidFilter {
+ @Override
+ boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
+ if (uuids != null) {
+ if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS)) {
+ return true;
+ }
+ if (BluetoothUuid.containsAnyUuid(uuids, HeadsetProfile.UUIDS)) {
+ return true;
+ }
+ } else if (btClass != null) {
+ if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
+ btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /** Filter that matches devices that support Object Transfer. */
+ private static final class TransferFilter extends ClassUuidFilter {
+ @Override
+ boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
+ if (uuids != null) {
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
+ return true;
+ }
+ }
+ return btClass != null
+ && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
+ }
+ }
+
+ /** Filter that matches devices that support PAN User (PANU) profile. */
+ private static final class PanuFilter extends ClassUuidFilter {
+ @Override
+ boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
+ if (uuids != null) {
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.PANU)) {
+ return true;
+ }
+ }
+ return btClass != null
+ && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
+ }
+ }
+
+ /** Filter that matches devices that support NAP profile. */
+ private static final class NapFilter extends ClassUuidFilter {
+ @Override
+ boolean matches(ParcelUuid[] uuids, BluetoothClass btClass) {
+ if (uuids != null) {
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP)) {
+ return true;
+ }
+ }
+ return btClass != null
+ && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
new file mode 100644
index 0000000..acb7e7a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+/* Required to handle timeout notification when phone is suspended */
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+
+public class BluetoothDiscoverableTimeoutReceiver extends BroadcastReceiver {
+ private static final String TAG = "BluetoothDiscoverableTimeoutReceiver";
+
+ private static final String INTENT_DISCOVERABLE_TIMEOUT =
+ "android.bluetooth.intent.DISCOVERABLE_TIMEOUT";
+
+ public static void setDiscoverableAlarm(Context context, long alarmTime) {
+ Log.d(TAG, "setDiscoverableAlarm(): alarmTime = " + alarmTime);
+
+ Intent intent = new Intent(INTENT_DISCOVERABLE_TIMEOUT);
+ intent.setClass(context, BluetoothDiscoverableTimeoutReceiver.class);
+ PendingIntent pending = PendingIntent.getBroadcast(
+ context, 0, intent, 0);
+ AlarmManager alarmManager =
+ (AlarmManager) context.getSystemService (Context.ALARM_SERVICE);
+
+ if (pending != null) {
+ // Cancel any previous alarms that do the same thing.
+ alarmManager.cancel(pending);
+ Log.d(TAG, "setDiscoverableAlarm(): cancel prev alarm");
+ }
+ pending = PendingIntent.getBroadcast(
+ context, 0, intent, 0);
+
+ alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pending);
+ }
+
+ public static void cancelDiscoverableAlarm(Context context) {
+ Log.d(TAG, "cancelDiscoverableAlarm(): Enter");
+
+ Intent intent = new Intent(INTENT_DISCOVERABLE_TIMEOUT);
+ intent.setClass(context, BluetoothDiscoverableTimeoutReceiver.class);
+ PendingIntent pending = PendingIntent.getBroadcast(
+ context, 0, intent, PendingIntent.FLAG_NO_CREATE);
+ if (pending != null) {
+ // Cancel any previous alarms that do the same thing.
+ AlarmManager alarmManager =
+ (AlarmManager) context.getSystemService (Context.ALARM_SERVICE);
+
+ alarmManager.cancel(pending);
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ LocalBluetoothAdapter localBluetoothAdapter = LocalBluetoothAdapter.getInstance();
+
+ if(localBluetoothAdapter != null &&
+ localBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
+ Log.d(TAG, "Disable discoverable...");
+
+ localBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+ } else {
+ Log.e(TAG, "localBluetoothAdapter is NULL!!");
+ }
+ }
+};
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
new file mode 100755
index 0000000..7c92368
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth
+ * API and dispatches the event on the UI thread to the right class in the
+ * Settings.
+ */
+public final class BluetoothEventManager {
+ private static final String TAG = "BluetoothEventManager";
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private LocalBluetoothProfileManager mProfileManager;
+ private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter;
+ private final Map<String, Handler> mHandlerMap;
+ private Context mContext;
+
+ private final Collection<BluetoothCallback> mCallbacks =
+ new ArrayList<BluetoothCallback>();
+
+ interface Handler {
+ void onReceive(Context context, Intent intent, BluetoothDevice device);
+ }
+
+ void addHandler(String action, Handler handler) {
+ mHandlerMap.put(action, handler);
+ mAdapterIntentFilter.addAction(action);
+ }
+
+ void addProfileHandler(String action, Handler handler) {
+ mHandlerMap.put(action, handler);
+ mProfileIntentFilter.addAction(action);
+ }
+
+ // Set profile manager after construction due to circular dependency
+ void setProfileManager(LocalBluetoothProfileManager manager) {
+ mProfileManager = manager;
+ }
+
+ BluetoothEventManager(LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager, Context context) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mAdapterIntentFilter = new IntentFilter();
+ mProfileIntentFilter = new IntentFilter();
+ mHandlerMap = new HashMap<String, Handler>();
+ mContext = context;
+
+ // Bluetooth on/off broadcasts
+ addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
+
+ // Discovery broadcasts
+ addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
+ addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
+ addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
+ addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
+ addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
+
+ // Pairing broadcasts
+ addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
+ addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, new PairingCancelHandler());
+
+ // Fine-grained state broadcasts
+ addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
+ addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
+
+ // Dock event broadcasts
+ addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
+
+ mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter);
+ }
+
+ void registerProfileIntentReceiver() {
+ mContext.registerReceiver(mBroadcastReceiver, mProfileIntentFilter);
+ }
+
+ /** Register to start receiving callbacks for Bluetooth events. */
+ public void registerCallback(BluetoothCallback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.add(callback);
+ }
+ }
+
+ /** Unregister to stop receiving callbacks for Bluetooth events. */
+ public void unregisterCallback(BluetoothCallback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.remove(callback);
+ }
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ BluetoothDevice device = intent
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+ Handler handler = mHandlerMap.get(action);
+ if (handler != null) {
+ handler.onReceive(context, intent, device);
+ }
+ }
+ };
+
+ private class AdapterStateChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
+ BluetoothAdapter.ERROR);
+ // update local profiles and get paired devices
+ mLocalAdapter.setBluetoothStateInt(state);
+ // send callback to update UI and possibly start scanning
+ synchronized (mCallbacks) {
+ for (BluetoothCallback callback : mCallbacks) {
+ callback.onBluetoothStateChanged(state);
+ }
+ }
+ // Inform CachedDeviceManager that the adapter state has changed
+ mDeviceManager.onBluetoothStateChanged(state);
+ }
+ }
+
+ private class ScanningStateChangedHandler implements Handler {
+ private final boolean mStarted;
+
+ ScanningStateChangedHandler(boolean started) {
+ mStarted = started;
+ }
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ synchronized (mCallbacks) {
+ for (BluetoothCallback callback : mCallbacks) {
+ callback.onScanningStateChanged(mStarted);
+ }
+ }
+ mDeviceManager.onScanningStateChanged(mStarted);
+ }
+ }
+
+ private class DeviceFoundHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
+ BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
+ String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
+ // TODO Pick up UUID. They should be available for 2.1 devices.
+ // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
+ Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ + cachedDevice);
+ // callback to UI to create Preference for new device
+ dispatchDeviceAdded(cachedDevice);
+ }
+ cachedDevice.setRssi(rssi);
+ cachedDevice.setBtClass(btClass);
+ cachedDevice.setNewName(name);
+ cachedDevice.setVisible(true);
+ }
+ }
+
+ private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
+ synchronized (mCallbacks) {
+ for (BluetoothCallback callback : mCallbacks) {
+ callback.onDeviceAdded(cachedDevice);
+ }
+ }
+ }
+
+ private class DeviceDisappearedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device);
+ return;
+ }
+ if (CachedBluetoothDeviceManager.onDeviceDisappeared(cachedDevice)) {
+ synchronized (mCallbacks) {
+ for (BluetoothCallback callback : mCallbacks) {
+ callback.onDeviceDeleted(cachedDevice);
+ }
+ }
+ }
+ }
+ }
+
+ private class NameChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ mDeviceManager.onDeviceNameUpdated(device);
+ }
+ }
+
+ private class BondStateChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ if (device == null) {
+ Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
+ return;
+ }
+ int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
+ BluetoothDevice.ERROR);
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ Log.w(TAG, "CachedBluetoothDevice for device " + device +
+ " not found, calling readPairedDevices().");
+ if (!readPairedDevices()) {
+ Log.e(TAG, "Got bonding state changed for " + device +
+ ", but we have no record of that device.");
+ return;
+ }
+ cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ Log.e(TAG, "Got bonding state changed for " + device +
+ ", but device not added in cache.");
+ return;
+ }
+ }
+
+ synchronized (mCallbacks) {
+ for (BluetoothCallback callback : mCallbacks) {
+ callback.onDeviceBondStateChanged(cachedDevice, bondState);
+ }
+ }
+ cachedDevice.onBondingStateChanged(bondState);
+
+ if (bondState == BluetoothDevice.BOND_NONE) {
+ int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
+ BluetoothDevice.ERROR);
+
+ showUnbondMessage(context, cachedDevice.getName(), reason);
+ }
+ }
+
+ /**
+ * Called when we have reached the unbonded state.
+ *
+ * @param reason one of the error reasons from
+ * BluetoothDevice.UNBOND_REASON_*
+ */
+ private void showUnbondMessage(Context context, String name, int reason) {
+ int errorMsg;
+
+ switch(reason) {
+ case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
+ errorMsg = R.string.bluetooth_pairing_pin_error_message;
+ break;
+ case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
+ errorMsg = R.string.bluetooth_pairing_rejected_error_message;
+ break;
+ case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
+ errorMsg = R.string.bluetooth_pairing_device_down_error_message;
+ break;
+ case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
+ case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
+ case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
+ case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
+ errorMsg = R.string.bluetooth_pairing_error_message;
+ break;
+ default:
+ Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
+ return;
+ }
+ Utils.showError(context, name, errorMsg);
+ }
+ }
+
+ private class ClassChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ mDeviceManager.onBtClassChanged(device);
+ }
+ }
+
+ private class UuidChangedHandler implements Handler {
+ public void onReceive(Context context, Intent intent,
+ BluetoothDevice device) {
+ mDeviceManager.onUuidChanged(device);
+ }
+ }
+
+ private class PairingCancelHandler implements Handler {
+ public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+ if (device == null) {
+ Log.e(TAG, "ACTION_PAIRING_CANCEL with no EXTRA_DEVICE");
+ return;
+ }
+ int errorMsg = R.string.bluetooth_pairing_error_message;
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ Utils.showError(context, cachedDevice.getName(), errorMsg);
+ }
+ }
+
+ private class DockEventHandler implements Handler {
+ public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+ // Remove if unpair device upon undocking
+ int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1;
+ int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked);
+ if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+ if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.setVisible(false);
+ }
+ }
+ }
+ }
+ }
+ boolean readPairedDevices() {
+ Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
+ if (bondedDevices == null) {
+ return false;
+ }
+
+ boolean deviceAdded = false;
+ for (BluetoothDevice device : bondedDevices) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
+ dispatchDeviceAdded(cachedDevice);
+ deviceAdded = true;
+ }
+ }
+
+ return deviceAdded;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
new file mode 100755
index 0000000..ddcc49f7
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.ParcelUuid;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.Log;
+import android.bluetooth.BluetoothAdapter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * CachedBluetoothDevice represents a remote Bluetooth device. It contains
+ * attributes of the device (such as the address, name, RSSI, etc.) and
+ * functionality that can be performed on the device (connect, pair, disconnect,
+ * etc.).
+ */
+public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
+ private static final String TAG = "CachedBluetoothDevice";
+ private static final boolean DEBUG = Utils.V;
+
+ private final Context mContext;
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final LocalBluetoothProfileManager mProfileManager;
+ private final BluetoothDevice mDevice;
+ private String mName;
+ private short mRssi;
+ private BluetoothClass mBtClass;
+ private HashMap<LocalBluetoothProfile, Integer> mProfileConnectionState;
+
+ private final List<LocalBluetoothProfile> mProfiles =
+ new ArrayList<LocalBluetoothProfile>();
+
+ // List of profiles that were previously in mProfiles, but have been removed
+ private final List<LocalBluetoothProfile> mRemovedProfiles =
+ new ArrayList<LocalBluetoothProfile>();
+
+ // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP
+ private boolean mLocalNapRoleConnected;
+
+ private boolean mVisible;
+
+ private int mPhonebookPermissionChoice;
+
+ private int mMessagePermissionChoice;
+
+ private int mMessageRejectionCount;
+
+ private final Collection<Callback> mCallbacks = new ArrayList<Callback>();
+
+ // Following constants indicate the user's choices of Phone book/message access settings
+ // User hasn't made any choice or settings app has wiped out the memory
+ public final static int ACCESS_UNKNOWN = 0;
+ // User has accepted the connection and let Settings app remember the decision
+ public final static int ACCESS_ALLOWED = 1;
+ // User has rejected the connection and let Settings app remember the decision
+ public final static int ACCESS_REJECTED = 2;
+
+ // How many times user should reject the connection to make the choice persist.
+ private final static int MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST = 2;
+
+ private final static String MESSAGE_REJECTION_COUNT_PREFS_NAME = "bluetooth_message_reject";
+
+ /**
+ * When we connect to multiple profiles, we only want to display a single
+ * error even if they all fail. This tracks that state.
+ */
+ private boolean mIsConnectingErrorPossible;
+
+ /**
+ * Last time a bt profile auto-connect was attempted.
+ * If an ACTION_UUID intent comes in within
+ * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect
+ * again with the new UUIDs
+ */
+ private long mConnectAttempted;
+
+ // See mConnectAttempted
+ private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
+
+ /** Auto-connect after pairing only if locally initiated. */
+ private boolean mConnectAfterPairing;
+
+ /**
+ * Describes the current device and profile for logging.
+ *
+ * @param profile Profile to describe
+ * @return Description of the device and profile
+ */
+ private String describe(LocalBluetoothProfile profile) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Address:").append(mDevice);
+ if (profile != null) {
+ sb.append(" Profile:").append(profile);
+ }
+
+ return sb.toString();
+ }
+
+ void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) {
+ if (Utils.D) {
+ Log.d(TAG, "onProfileStateChanged: profile " + profile +
+ " newProfileState " + newProfileState);
+ }
+ if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF)
+ {
+ if (Utils.D) Log.d(TAG, " BT Turninig Off...Profile conn state change ignored...");
+ return;
+ }
+ mProfileConnectionState.put(profile, newProfileState);
+ if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
+ if (profile instanceof MapProfile) {
+ profile.setPreferred(mDevice, true);
+ } else if (!mProfiles.contains(profile)) {
+ mRemovedProfiles.remove(profile);
+ mProfiles.add(profile);
+ if (profile instanceof PanProfile &&
+ ((PanProfile) profile).isLocalRoleNap(mDevice)) {
+ // Device doesn't support NAP, so remove PanProfile on disconnect
+ mLocalNapRoleConnected = true;
+ }
+ }
+ } else if (profile instanceof MapProfile &&
+ newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
+ profile.setPreferred(mDevice, false);
+ } else if (mLocalNapRoleConnected && profile instanceof PanProfile &&
+ ((PanProfile) profile).isLocalRoleNap(mDevice) &&
+ newProfileState == BluetoothProfile.STATE_DISCONNECTED) {
+ Log.d(TAG, "Removing PanProfile from device after NAP disconnect");
+ mProfiles.remove(profile);
+ mRemovedProfiles.add(profile);
+ mLocalNapRoleConnected = false;
+ }
+ }
+
+ CachedBluetoothDevice(Context context,
+ LocalBluetoothAdapter adapter,
+ LocalBluetoothProfileManager profileManager,
+ BluetoothDevice device) {
+ mContext = context;
+ mLocalAdapter = adapter;
+ mProfileManager = profileManager;
+ mDevice = device;
+ mProfileConnectionState = new HashMap<LocalBluetoothProfile, Integer>();
+ fillData();
+ }
+
+ public void disconnect() {
+ for (LocalBluetoothProfile profile : mProfiles) {
+ disconnect(profile);
+ }
+ // Disconnect PBAP server in case its connected
+ // This is to ensure all the profiles are disconnected as some CK/Hs do not
+ // disconnect PBAP connection when HF connection is brought down
+ PbapServerProfile PbapProfile = mProfileManager.getPbapProfile();
+ if (PbapProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED)
+ {
+ PbapProfile.disconnect(mDevice);
+ }
+ }
+
+ public void disconnect(LocalBluetoothProfile profile) {
+ if (profile.disconnect(mDevice)) {
+ if (Utils.D) {
+ Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile));
+ }
+ }
+ }
+
+ public void connect(boolean connectAllProfiles) {
+ if (!ensurePaired()) {
+ return;
+ }
+
+ mConnectAttempted = SystemClock.elapsedRealtime();
+ connectWithoutResettingTimer(connectAllProfiles);
+ }
+
+ void onBondingDockConnect() {
+ // Attempt to connect if UUIDs are available. Otherwise,
+ // we will connect when the ACTION_UUID intent arrives.
+ connect(false);
+ }
+
+ private void connectWithoutResettingTimer(boolean connectAllProfiles) {
+ // Try to initialize the profiles if they were not.
+ if (mProfiles.isEmpty()) {
+ // if mProfiles is empty, then do not invoke updateProfiles. This causes a race
+ // condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated
+ // from bluetooth stack but ACTION.uuid is not sent yet.
+ // Eventually ACTION.uuid will be received which shall trigger the connection of the
+ // various profiles
+ // If UUIDs are not available yet, connect will be happen
+ // upon arrival of the ACTION_UUID intent.
+ Log.d(TAG, "No profiles. Maybe we will connect later");
+ return;
+ }
+
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+
+ int preferredProfiles = 0;
+ for (LocalBluetoothProfile profile : mProfiles) {
+ if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
+ if (profile.isPreferred(mDevice)) {
+ ++preferredProfiles;
+ connectInt(profile);
+ }
+ }
+ }
+ if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles);
+
+ if (preferredProfiles == 0) {
+ connectAutoConnectableProfiles();
+ }
+ }
+
+ private void connectAutoConnectableProfiles() {
+ if (!ensurePaired()) {
+ return;
+ }
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+
+ for (LocalBluetoothProfile profile : mProfiles) {
+ if (profile.isAutoConnectable()) {
+ profile.setPreferred(mDevice, true);
+ connectInt(profile);
+ }
+ }
+ }
+
+ /**
+ * Connect this device to the specified profile.
+ *
+ * @param profile the profile to use with the remote device
+ */
+ public void connectProfile(LocalBluetoothProfile profile) {
+ mConnectAttempted = SystemClock.elapsedRealtime();
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+ connectInt(profile);
+ // Refresh the UI based on profile.connect() call
+ refresh();
+ }
+
+ synchronized void connectInt(LocalBluetoothProfile profile) {
+ if (!ensurePaired()) {
+ return;
+ }
+ if (profile.connect(mDevice)) {
+ if (Utils.D) {
+ Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));
+ }
+ return;
+ }
+ Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
+ }
+
+ private boolean ensurePaired() {
+ if (getBondState() == BluetoothDevice.BOND_NONE) {
+ startPairing();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public boolean startPairing() {
+ // Pairing is unreliable while scanning, so cancel discovery
+ if (mLocalAdapter.isDiscovering()) {
+ mLocalAdapter.cancelDiscovery();
+ }
+
+ if (!mDevice.createBond()) {
+ return false;
+ }
+
+ mConnectAfterPairing = true; // auto-connect after pairing
+ return true;
+ }
+
+ /**
+ * Return true if user initiated pairing on this device. The message text is
+ * slightly different for local vs. remote initiated pairing dialogs.
+ */
+ boolean isUserInitiatedPairing() {
+ return mConnectAfterPairing;
+ }
+
+ public void unpair() {
+ int state = getBondState();
+
+ if (state == BluetoothDevice.BOND_BONDING) {
+ mDevice.cancelBondProcess();
+ }
+
+ if (state != BluetoothDevice.BOND_NONE) {
+ final BluetoothDevice dev = mDevice;
+ if (dev != null) {
+ final boolean successful = dev.removeBond();
+ if (successful) {
+ if (Utils.D) {
+ Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null));
+ }
+ } else if (Utils.V) {
+ Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " +
+ describe(null));
+ }
+ }
+ }
+ }
+
+ public int getProfileConnectionState(LocalBluetoothProfile profile) {
+ if (mProfileConnectionState == null ||
+ mProfileConnectionState.get(profile) == null) {
+ // If cache is empty make the binder call to get the state
+ int state = profile.getConnectionStatus(mDevice);
+ mProfileConnectionState.put(profile, state);
+ }
+ return mProfileConnectionState.get(profile);
+ }
+
+ public void clearProfileConnectionState ()
+ {
+ if (Utils.D) {
+ Log.d(TAG," Clearing all connection state for dev:" + mDevice.getName());
+ }
+ for (LocalBluetoothProfile profile :getProfiles()) {
+ mProfileConnectionState.put(profile, BluetoothProfile.STATE_DISCONNECTED);
+ }
+ }
+
+ // TODO: do any of these need to run async on a background thread?
+ private void fillData() {
+ fetchName();
+ fetchBtClass();
+ updateProfiles();
+ migratePhonebookPermissionChoice();
+ migrateMessagePermissionChoice();
+ fetchMessageRejectionCount();
+
+ mVisible = false;
+ dispatchAttributesChanged();
+ }
+
+ public BluetoothDevice getDevice() {
+ return mDevice;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Populate name from BluetoothDevice.ACTION_FOUND intent
+ */
+ void setNewName(String name) {
+ if (mName == null) {
+ mName = name;
+ if (mName == null || TextUtils.isEmpty(mName)) {
+ mName = mDevice.getAddress();
+ }
+ dispatchAttributesChanged();
+ }
+ }
+
+ /**
+ * user changes the device name
+ */
+ public void setName(String name) {
+ if (!mName.equals(name)) {
+ mName = name;
+ mDevice.setAlias(name);
+ dispatchAttributesChanged();
+ }
+ }
+
+ void refreshName() {
+ fetchName();
+ dispatchAttributesChanged();
+ }
+
+ private void fetchName() {
+ mName = mDevice.getAliasName();
+
+ if (TextUtils.isEmpty(mName)) {
+ mName = mDevice.getAddress();
+ if (DEBUG) Log.d(TAG, "Device has no name (yet), use address: " + mName);
+ }
+ }
+
+ void refresh() {
+ dispatchAttributesChanged();
+ }
+
+ public boolean isVisible() {
+ return mVisible;
+ }
+
+ public void setVisible(boolean visible) {
+ if (mVisible != visible) {
+ mVisible = visible;
+ dispatchAttributesChanged();
+ }
+ }
+
+ public int getBondState() {
+ return mDevice.getBondState();
+ }
+
+ void setRssi(short rssi) {
+ if (mRssi != rssi) {
+ mRssi = rssi;
+ dispatchAttributesChanged();
+ }
+ }
+
+ /**
+ * Checks whether we are connected to this device (any profile counts).
+ *
+ * @return Whether it is connected.
+ */
+ public boolean isConnected() {
+ for (LocalBluetoothProfile profile : mProfiles) {
+ int status = getProfileConnectionState(profile);
+ if (status == BluetoothProfile.STATE_CONNECTED) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isConnectedProfile(LocalBluetoothProfile profile) {
+ int status = getProfileConnectionState(profile);
+ return status == BluetoothProfile.STATE_CONNECTED;
+
+ }
+
+ public boolean isBusy() {
+ for (LocalBluetoothProfile profile : mProfiles) {
+ int status = getProfileConnectionState(profile);
+ if (status == BluetoothProfile.STATE_CONNECTING
+ || status == BluetoothProfile.STATE_DISCONNECTING) {
+ return true;
+ }
+ }
+ return getBondState() == BluetoothDevice.BOND_BONDING;
+ }
+
+ /**
+ * Fetches a new value for the cached BT class.
+ */
+ private void fetchBtClass() {
+ mBtClass = mDevice.getBluetoothClass();
+ }
+
+ private boolean updateProfiles() {
+ ParcelUuid[] uuids = mDevice.getUuids();
+ if (uuids == null) return false;
+
+ ParcelUuid[] localUuids = mLocalAdapter.getUuids();
+ if (localUuids == null) return false;
+
+ /**
+ * Now we know if the device supports PBAP, update permissions...
+ */
+ processPhonebookAccess();
+
+ mProfileManager.updateProfiles(uuids, localUuids, mProfiles, mRemovedProfiles,
+ mLocalNapRoleConnected, mDevice);
+
+ if (DEBUG) {
+ Log.e(TAG, "updating profiles for " + mDevice.getAliasName());
+ BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
+
+ if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
+ Log.v(TAG, "UUID:");
+ for (ParcelUuid uuid : uuids) {
+ Log.v(TAG, " " + uuid);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Refreshes the UI for the BT class, including fetching the latest value
+ * for the class.
+ */
+ void refreshBtClass() {
+ fetchBtClass();
+ dispatchAttributesChanged();
+ }
+
+ /**
+ * Refreshes the UI when framework alerts us of a UUID change.
+ */
+ void onUuidChanged() {
+ updateProfiles();
+
+ if (DEBUG) {
+ Log.e(TAG, "onUuidChanged: Time since last connect"
+ + (SystemClock.elapsedRealtime() - mConnectAttempted));
+ }
+
+ /*
+ * If a connect was attempted earlier without any UUID, we will do the
+ * connect now.
+ */
+ if (!mProfiles.isEmpty()
+ && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock
+ .elapsedRealtime()) {
+ connectWithoutResettingTimer(false);
+ }
+ dispatchAttributesChanged();
+ }
+
+ void onBondingStateChanged(int bondState) {
+ if (bondState == BluetoothDevice.BOND_NONE) {
+ mProfiles.clear();
+ mConnectAfterPairing = false; // cancel auto-connect
+ setPhonebookPermissionChoice(ACCESS_UNKNOWN);
+ setMessagePermissionChoice(ACCESS_UNKNOWN);
+ mMessageRejectionCount = 0;
+ saveMessageRejectionCount();
+ }
+
+ refresh();
+
+ if (bondState == BluetoothDevice.BOND_BONDED) {
+ if (mDevice.isBluetoothDock()) {
+ onBondingDockConnect();
+ } else if (mConnectAfterPairing) {
+ connect(false);
+ }
+ mConnectAfterPairing = false;
+ }
+ }
+
+ void setBtClass(BluetoothClass btClass) {
+ if (btClass != null && mBtClass != btClass) {
+ mBtClass = btClass;
+ dispatchAttributesChanged();
+ }
+ }
+
+ public BluetoothClass getBtClass() {
+ return mBtClass;
+ }
+
+ public List<LocalBluetoothProfile> getProfiles() {
+ return Collections.unmodifiableList(mProfiles);
+ }
+
+ public List<LocalBluetoothProfile> getConnectableProfiles() {
+ List<LocalBluetoothProfile> connectableProfiles =
+ new ArrayList<LocalBluetoothProfile>();
+ for (LocalBluetoothProfile profile : mProfiles) {
+ if (profile.isConnectable()) {
+ connectableProfiles.add(profile);
+ }
+ }
+ return connectableProfiles;
+ }
+
+ public List<LocalBluetoothProfile> getRemovedProfiles() {
+ return mRemovedProfiles;
+ }
+
+ public void registerCallback(Callback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.add(callback);
+ }
+ }
+
+ public void unregisterCallback(Callback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.remove(callback);
+ }
+ }
+
+ private void dispatchAttributesChanged() {
+ synchronized (mCallbacks) {
+ for (Callback callback : mCallbacks) {
+ callback.onDeviceAttributesChanged();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return mDevice.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof CachedBluetoothDevice)) {
+ return false;
+ }
+ return mDevice.equals(((CachedBluetoothDevice) o).mDevice);
+ }
+
+ @Override
+ public int hashCode() {
+ return mDevice.getAddress().hashCode();
+ }
+
+ // This comparison uses non-final fields so the sort order may change
+ // when device attributes change (such as bonding state). Settings
+ // will completely refresh the device list when this happens.
+ public int compareTo(CachedBluetoothDevice another) {
+ // Connected above not connected
+ int comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0);
+ if (comparison != 0) return comparison;
+
+ // Paired above not paired
+ comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) -
+ (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
+ if (comparison != 0) return comparison;
+
+ // Visible above not visible
+ comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0);
+ if (comparison != 0) return comparison;
+
+ // Stronger signal above weaker signal
+ comparison = another.mRssi - mRssi;
+ if (comparison != 0) return comparison;
+
+ // Fallback on name
+ return mName.compareTo(another.mName);
+ }
+
+ public interface Callback {
+ void onDeviceAttributesChanged();
+ }
+
+ public int getPhonebookPermissionChoice() {
+ int permission = mDevice.getPhonebookAccessPermission();
+ if (permission == BluetoothDevice.ACCESS_ALLOWED) {
+ return ACCESS_ALLOWED;
+ } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
+ return ACCESS_REJECTED;
+ }
+ return ACCESS_UNKNOWN;
+ }
+
+ public void setPhonebookPermissionChoice(int permissionChoice) {
+ int permission = BluetoothDevice.ACCESS_UNKNOWN;
+ if (permissionChoice == ACCESS_ALLOWED) {
+ permission = BluetoothDevice.ACCESS_ALLOWED;
+ } else if (permissionChoice == ACCESS_REJECTED) {
+ permission = BluetoothDevice.ACCESS_REJECTED;
+ }
+ mDevice.setPhonebookAccessPermission(permission);
+ }
+
+ // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
+ // app's shared preferences).
+ private void migratePhonebookPermissionChoice() {
+ SharedPreferences preferences = mContext.getSharedPreferences(
+ "bluetooth_phonebook_permission", Context.MODE_PRIVATE);
+ if (!preferences.contains(mDevice.getAddress())) {
+ return;
+ }
+
+ if (mDevice.getPhonebookAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
+ int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
+ if (oldPermission == ACCESS_ALLOWED) {
+ mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
+ } else if (oldPermission == ACCESS_REJECTED) {
+ mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
+ }
+ }
+
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.remove(mDevice.getAddress());
+ editor.commit();
+ }
+
+ public int getMessagePermissionChoice() {
+ int permission = mDevice.getMessageAccessPermission();
+ if (permission == BluetoothDevice.ACCESS_ALLOWED) {
+ return ACCESS_ALLOWED;
+ } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
+ return ACCESS_REJECTED;
+ }
+ return ACCESS_UNKNOWN;
+ }
+
+ public void setMessagePermissionChoice(int permissionChoice) {
+ int permission = BluetoothDevice.ACCESS_UNKNOWN;
+ if (permissionChoice == ACCESS_ALLOWED) {
+ permission = BluetoothDevice.ACCESS_ALLOWED;
+ } else if (permissionChoice == ACCESS_REJECTED) {
+ permission = BluetoothDevice.ACCESS_REJECTED;
+ }
+ mDevice.setMessageAccessPermission(permission);
+ }
+
+ // Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
+ // app's shared preferences).
+ private void migrateMessagePermissionChoice() {
+ SharedPreferences preferences = mContext.getSharedPreferences(
+ "bluetooth_message_permission", Context.MODE_PRIVATE);
+ if (!preferences.contains(mDevice.getAddress())) {
+ return;
+ }
+
+ if (mDevice.getMessageAccessPermission() == BluetoothDevice.ACCESS_UNKNOWN) {
+ int oldPermission = preferences.getInt(mDevice.getAddress(), ACCESS_UNKNOWN);
+ if (oldPermission == ACCESS_ALLOWED) {
+ mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
+ } else if (oldPermission == ACCESS_REJECTED) {
+ mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED);
+ }
+ }
+
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.remove(mDevice.getAddress());
+ editor.commit();
+ }
+
+ /**
+ * @return Whether this rejection should persist.
+ */
+ public boolean checkAndIncreaseMessageRejectionCount() {
+ if (mMessageRejectionCount < MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST) {
+ mMessageRejectionCount++;
+ saveMessageRejectionCount();
+ }
+ return mMessageRejectionCount >= MESSAGE_REJECTION_COUNT_LIMIT_TO_PERSIST;
+ }
+
+ private void fetchMessageRejectionCount() {
+ SharedPreferences preference = mContext.getSharedPreferences(
+ MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE);
+ mMessageRejectionCount = preference.getInt(mDevice.getAddress(), 0);
+ }
+
+ private void saveMessageRejectionCount() {
+ SharedPreferences.Editor editor = mContext.getSharedPreferences(
+ MESSAGE_REJECTION_COUNT_PREFS_NAME, Context.MODE_PRIVATE).edit();
+ if (mMessageRejectionCount == 0) {
+ editor.remove(mDevice.getAddress());
+ } else {
+ editor.putInt(mDevice.getAddress(), mMessageRejectionCount);
+ }
+ editor.commit();
+ }
+
+ private void processPhonebookAccess() {
+ if (mDevice.getBondState() != BluetoothDevice.BOND_BONDED) return;
+
+ ParcelUuid[] uuids = mDevice.getUuids();
+ if (BluetoothUuid.containsAnyUuid(uuids, PbapServerProfile.PBAB_CLIENT_UUIDS)) {
+ // The pairing dialog now warns of phone-book access for paired devices.
+ // No separate prompt is displayed after pairing.
+ setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
new file mode 100755
index 0000000..65db95f
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
+ */
+public final class CachedBluetoothDeviceManager {
+ private static final String TAG = "CachedBluetoothDeviceManager";
+ private static final boolean DEBUG = Utils.D;
+
+ private Context mContext;
+ private final List<CachedBluetoothDevice> mCachedDevices =
+ new ArrayList<CachedBluetoothDevice>();
+
+ CachedBluetoothDeviceManager(Context context) {
+ mContext = context;
+ }
+
+ public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
+ return new ArrayList<CachedBluetoothDevice>(mCachedDevices);
+ }
+
+ public static boolean onDeviceDisappeared(CachedBluetoothDevice cachedDevice) {
+ cachedDevice.setVisible(false);
+ return cachedDevice.getBondState() == BluetoothDevice.BOND_NONE;
+ }
+
+ public void onDeviceNameUpdated(BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.refreshName();
+ }
+ }
+
+ /**
+ * Search for existing {@link CachedBluetoothDevice} or return null
+ * if this device isn't in the cache. Use {@link #addDevice}
+ * to create and return a new {@link CachedBluetoothDevice} for
+ * a newly discovered {@link BluetoothDevice}.
+ *
+ * @param device the address of the Bluetooth device
+ * @return the cached device object for this device, or null if it has
+ * not been previously seen
+ */
+ public CachedBluetoothDevice findDevice(BluetoothDevice device) {
+ for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+ if (cachedDevice.getDevice().equals(device)) {
+ return cachedDevice;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Create and return a new {@link CachedBluetoothDevice}. This assumes
+ * that {@link #findDevice} has already been called and returned null.
+ * @param device the address of the new Bluetooth device
+ * @return the newly created CachedBluetoothDevice object
+ */
+ public CachedBluetoothDevice addDevice(LocalBluetoothAdapter adapter,
+ LocalBluetoothProfileManager profileManager,
+ BluetoothDevice device) {
+ CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter,
+ profileManager, device);
+ synchronized (mCachedDevices) {
+ mCachedDevices.add(newDevice);
+ }
+ return newDevice;
+ }
+
+ /**
+ * Attempts to get the name of a remote device, otherwise returns the address.
+ *
+ * @param device The remote device.
+ * @return The name, or if unavailable, the address.
+ */
+ public String getName(BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = findDevice(device);
+ if (cachedDevice != null) {
+ return cachedDevice.getName();
+ }
+
+ String name = device.getAliasName();
+ if (name != null) {
+ return name;
+ }
+
+ return device.getAddress();
+ }
+
+ public synchronized void clearNonBondedDevices() {
+ for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+ if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+ mCachedDevices.remove(i);
+ }
+ }
+ }
+
+ public synchronized void onScanningStateChanged(boolean started) {
+ if (!started) return;
+
+ // If starting a new scan, clear old visibility
+ // 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);
+ }
+ }
+
+ public synchronized void onBtClassChanged(BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.refreshBtClass();
+ }
+ }
+
+ public synchronized void onUuidChanged(BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = findDevice(device);
+ if (cachedDevice != null) {
+ cachedDevice.onUuidChanged();
+ }
+ }
+
+ public synchronized void onBluetoothStateChanged(int bluetoothState) {
+ // When Bluetooth is turning off, we need to clear the non-bonded devices
+ // Otherwise, they end up showing up on the next BT enable
+ if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
+ for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+ CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+ if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+ cachedDevice.setVisible(false);
+ mCachedDevices.remove(i);
+ } else {
+ // For bonded devices, we need to clear the connection status so that
+ // when BT is enabled next time, device connection status shall be retrieved
+ // by making a binder call.
+ cachedDevice.clearProfileConnectionState();
+ }
+ }
+ }
+ }
+ private void log(String msg) {
+ if (DEBUG) {
+ Log.d(TAG, msg);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
new file mode 100755
index 0000000..5529866
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * HeadsetProfile handles Bluetooth HFP and Headset profiles.
+ */
+public final class HeadsetProfile implements LocalBluetoothProfile {
+ private static final String TAG = "HeadsetProfile";
+ private static boolean V = true;
+
+ private BluetoothHeadset mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ static final ParcelUuid[] UUIDS = {
+ BluetoothUuid.HSP,
+ BluetoothUuid.Handsfree,
+ };
+
+ static final String NAME = "HEADSET";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 0;
+
+ // These callbacks run on the main thread.
+ private final class HeadsetServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothHeadset) proxy;
+ // We just bound to the service, so refresh the UI for any connected HFP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "HeadsetProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(HeadsetProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+
+ mProfileManager.callServiceConnectedListeners();
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mProfileManager.callServiceDisconnectedListeners();
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ HeadsetProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new HeadsetServiceListener(),
+ BluetoothProfile.HEADSET);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> sinks = mService.getConnectedDevices();
+ if (sinks != null) {
+ for (BluetoothDevice sink : sinks) {
+ Log.d(TAG,"Not disconnecting device = " + sink);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty()) {
+ for (BluetoothDevice dev : deviceList) {
+ if (dev.equals(device)) {
+ if (V) Log.d(TAG,"Downgrade priority as user" +
+ "is disconnecting the headset");
+ // Downgrade priority as user is disconnecting the headset.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+ }
+ }
+ return false;
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty()){
+ for (BluetoothDevice dev : deviceList) {
+ if (dev.equals(device)) {
+ return mService.getConnectionState(device);
+ }
+ }
+ }
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_headset;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_headset_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_headset_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_headset_hfp;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HEADSET,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up HID proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
new file mode 100755
index 0000000..a9e8db5
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.List;
+
+/**
+ * HidProfile handles Bluetooth HID profile.
+ */
+public final class HidProfile implements LocalBluetoothProfile {
+ private static final String TAG = "HidProfile";
+ private static boolean V = true;
+
+ private BluetoothInputDevice mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ static final String NAME = "HID";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 3;
+
+ // These callbacks run on the main thread.
+ private final class InputDeviceServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothInputDevice) proxy;
+ // We just bound to the service, so refresh the UI for any connected HID devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "HidProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(HidProfile.this, BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ HidProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ adapter.getProfileProxy(context, new InputDeviceServiceListener(),
+ BluetoothProfile.INPUT_DEVICE);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+
+ return !deviceList.isEmpty() && deviceList.get(0).equals(device)
+ ? mService.getConnectionState(device)
+ : BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ // TODO: distinguish between keyboard and mouse?
+ return R.string.bluetooth_profile_hid;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_hid_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_hid_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ if (btClass == null) {
+ return R.drawable.ic_lockscreen_ime;
+ }
+ return getHidClassDrawable(btClass);
+ }
+
+ public static int getHidClassDrawable(BluetoothClass btClass) {
+ switch (btClass.getDeviceClass()) {
+ case BluetoothClass.Device.PERIPHERAL_KEYBOARD:
+ case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING:
+ return R.drawable.ic_lockscreen_ime;
+ case BluetoothClass.Device.PERIPHERAL_POINTING:
+ return R.drawable.ic_bt_pointing_hid;
+ default:
+ return R.drawable.ic_bt_misc_hid;
+ }
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.INPUT_DEVICE,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up HID proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
new file mode 100644
index 0000000..0c1adec
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import java.util.Set;
+
+/**
+ * LocalBluetoothAdapter provides an interface between the Settings app
+ * and the functionality of the local {@link BluetoothAdapter}, specifically
+ * those related to state transitions of the adapter itself.
+ *
+ * <p>Connection and bonding state changes affecting specific devices
+ * are handled by {@link CachedBluetoothDeviceManager},
+ * {@link BluetoothEventManager}, and {@link LocalBluetoothProfileManager}.
+ */
+public final class LocalBluetoothAdapter {
+ private static final String TAG = "LocalBluetoothAdapter";
+
+ /** This class does not allow direct access to the BluetoothAdapter. */
+ private final BluetoothAdapter mAdapter;
+
+ private LocalBluetoothProfileManager mProfileManager;
+
+ private static LocalBluetoothAdapter sInstance;
+
+ private int mState = BluetoothAdapter.ERROR;
+
+ private static final int SCAN_EXPIRATION_MS = 5 * 60 * 1000; // 5 mins
+
+ private long mLastScan;
+
+ private LocalBluetoothAdapter(BluetoothAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ void setProfileManager(LocalBluetoothProfileManager manager) {
+ mProfileManager = manager;
+ }
+
+ /**
+ * Get the singleton instance of the LocalBluetoothAdapter. If this device
+ * doesn't support Bluetooth, then null will be returned. Callers must be
+ * prepared to handle a null return value.
+ * @return the LocalBluetoothAdapter object, or null if not supported
+ */
+ static synchronized LocalBluetoothAdapter getInstance() {
+ if (sInstance == null) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null) {
+ sInstance = new LocalBluetoothAdapter(adapter);
+ }
+ }
+
+ return sInstance;
+ }
+
+ // Pass-through BluetoothAdapter methods that we can intercept if necessary
+
+ public void cancelDiscovery() {
+ mAdapter.cancelDiscovery();
+ }
+
+ public boolean enable() {
+ return mAdapter.enable();
+ }
+
+ public boolean disable() {
+ return mAdapter.disable();
+ }
+
+ void getProfileProxy(Context context,
+ BluetoothProfile.ServiceListener listener, int profile) {
+ mAdapter.getProfileProxy(context, listener, profile);
+ }
+
+ public Set<BluetoothDevice> getBondedDevices() {
+ return mAdapter.getBondedDevices();
+ }
+
+ public String getName() {
+ return mAdapter.getName();
+ }
+
+ public int getScanMode() {
+ return mAdapter.getScanMode();
+ }
+
+ public int getState() {
+ return mAdapter.getState();
+ }
+
+ public ParcelUuid[] getUuids() {
+ return mAdapter.getUuids();
+ }
+
+ public boolean isDiscovering() {
+ return mAdapter.isDiscovering();
+ }
+
+ public boolean isEnabled() {
+ return mAdapter.isEnabled();
+ }
+
+ public void setDiscoverableTimeout(int timeout) {
+ mAdapter.setDiscoverableTimeout(timeout);
+ }
+
+ public void setName(String name) {
+ mAdapter.setName(name);
+ }
+
+ public void setScanMode(int mode) {
+ mAdapter.setScanMode(mode);
+ }
+
+ public boolean setScanMode(int mode, int duration) {
+ return mAdapter.setScanMode(mode, duration);
+ }
+
+ public void startScanning(boolean force) {
+ // Only start if we're not already scanning
+ if (!mAdapter.isDiscovering()) {
+ if (!force) {
+ // Don't scan more than frequently than SCAN_EXPIRATION_MS,
+ // unless forced
+ if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {
+ return;
+ }
+
+ // If we are playing music, don't scan unless forced.
+ A2dpProfile a2dp = mProfileManager.getA2dpProfile();
+ if (a2dp != null && a2dp.isA2dpPlaying()) {
+ return;
+ }
+ }
+
+ if (mAdapter.startDiscovery()) {
+ mLastScan = System.currentTimeMillis();
+ }
+ }
+ }
+
+ public void stopScanning() {
+ if (mAdapter.isDiscovering()) {
+ mAdapter.cancelDiscovery();
+ }
+ }
+
+ public synchronized int getBluetoothState() {
+ // Always sync state, in case it changed while paused
+ syncBluetoothState();
+ return mState;
+ }
+
+ synchronized void setBluetoothStateInt(int state) {
+ mState = state;
+
+ if (state == BluetoothAdapter.STATE_ON) {
+ // if mProfileManager hasn't been constructed yet, it will
+ // get the adapter UUIDs in its constructor when it is.
+ if (mProfileManager != null) {
+ mProfileManager.setBluetoothStateOn();
+ }
+ }
+ }
+
+ // Returns true if the state changed; false otherwise.
+ boolean syncBluetoothState() {
+ int currentState = mAdapter.getState();
+ if (currentState != mState) {
+ setBluetoothStateInt(mAdapter.getState());
+ return true;
+ }
+ return false;
+ }
+
+ public void setBluetoothEnabled(boolean enabled) {
+ boolean success = enabled
+ ? mAdapter.enable()
+ : mAdapter.disable();
+
+ if (success) {
+ setBluetoothStateInt(enabled
+ ? BluetoothAdapter.STATE_TURNING_ON
+ : BluetoothAdapter.STATE_TURNING_OFF);
+ } else {
+ if (Utils.V) {
+ Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +
+ "success for enabled: " + enabled);
+ }
+
+ syncBluetoothState();
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
new file mode 100644
index 0000000..4adc62e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.content.Context;
+import android.util.Log;
+
+/**
+ * LocalBluetoothManager provides a simplified interface on top of a subset of
+ * the Bluetooth API. Note that {@link #getInstance} will return null
+ * if there is no Bluetooth adapter on this device, and callers must be
+ * prepared to handle this case.
+ */
+public final class LocalBluetoothManager {
+ private static final String TAG = "LocalBluetoothManager";
+
+ /** Singleton instance. */
+ private static LocalBluetoothManager sInstance;
+
+ private final Context mContext;
+
+ /** If a BT-related activity is in the foreground, this will be it. */
+ private Context mForegroundActivity;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+
+ private final CachedBluetoothDeviceManager mCachedDeviceManager;
+
+ /** The Bluetooth profile manager. */
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ /** The broadcast receiver event manager. */
+ private final BluetoothEventManager mEventManager;
+
+ public static synchronized LocalBluetoothManager getInstance(Context context,
+ BluetoothManagerCallback onInitCallback) {
+ if (sInstance == null) {
+ LocalBluetoothAdapter adapter = LocalBluetoothAdapter.getInstance();
+ if (adapter == null) {
+ return null;
+ }
+ // This will be around as long as this process is
+ Context appContext = context.getApplicationContext();
+ sInstance = new LocalBluetoothManager(adapter, appContext);
+ if (onInitCallback != null) {
+ onInitCallback.onBluetoothManagerInitialized(appContext, sInstance);
+ }
+ }
+
+ return sInstance;
+ }
+
+ private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context) {
+ mContext = context;
+ mLocalAdapter = adapter;
+
+ mCachedDeviceManager = new CachedBluetoothDeviceManager(context);
+ mEventManager = new BluetoothEventManager(mLocalAdapter,
+ mCachedDeviceManager, context);
+ mProfileManager = new LocalBluetoothProfileManager(context,
+ mLocalAdapter, mCachedDeviceManager, mEventManager);
+ }
+
+ public LocalBluetoothAdapter getBluetoothAdapter() {
+ return mLocalAdapter;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public Context getForegroundActivity() {
+ return mForegroundActivity;
+ }
+
+ public boolean isForegroundActivity() {
+ return mForegroundActivity != null;
+ }
+
+ public synchronized void setForegroundActivity(Context context) {
+ if (context != null) {
+ Log.d(TAG, "setting foreground activity to non-null context");
+ mForegroundActivity = context;
+ } else {
+ if (mForegroundActivity != null) {
+ Log.d(TAG, "setting foreground activity to null");
+ mForegroundActivity = null;
+ }
+ }
+ }
+
+ public CachedBluetoothDeviceManager getCachedDeviceManager() {
+ return mCachedDeviceManager;
+ }
+
+ public BluetoothEventManager getEventManager() {
+ return mEventManager;
+ }
+
+ public LocalBluetoothProfileManager getProfileManager() {
+ return mProfileManager;
+ }
+
+ public interface BluetoothManagerCallback {
+ void onBluetoothManagerInitialized(Context appContext,
+ LocalBluetoothManager bluetoothManager);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
new file mode 100755
index 0000000..abcb989
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * LocalBluetoothProfile is an interface defining the basic
+ * functionality related to a Bluetooth profile.
+ */
+public interface LocalBluetoothProfile {
+
+ /**
+ * Returns true if the user can initiate a connection, false otherwise.
+ */
+ boolean isConnectable();
+
+ /**
+ * Returns true if the user can enable auto connection for this profile.
+ */
+ boolean isAutoConnectable();
+
+ boolean connect(BluetoothDevice device);
+
+ boolean disconnect(BluetoothDevice device);
+
+ int getConnectionStatus(BluetoothDevice device);
+
+ boolean isPreferred(BluetoothDevice device);
+
+ int getPreferred(BluetoothDevice device);
+
+ void setPreferred(BluetoothDevice device, boolean preferred);
+
+ boolean isProfileReady();
+
+ /** Display order for device profile settings. */
+ int getOrdinal();
+
+ /**
+ * Returns the string resource ID for the localized name for this profile.
+ * @param device the Bluetooth device (to distinguish between PAN roles)
+ */
+ int getNameResource(BluetoothDevice device);
+
+ /**
+ * Returns the string resource ID for the summary text for this profile
+ * for the specified device, e.g. "Use for media audio" or
+ * "Connected to media audio".
+ * @param device the device to query for profile connection status
+ * @return a string resource ID for the profile summary text
+ */
+ int getSummaryResourceForDevice(BluetoothDevice device);
+
+ int getDrawableResource(BluetoothClass btClass);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
new file mode 100644
index 0000000..b0a7b27
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothMap;
+import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothPbap;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelUuid;
+import android.util.Log;
+import android.os.Handler;
+import android.os.Message;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+
+/**
+ * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
+ * objects for the available Bluetooth profiles.
+ */
+public final class LocalBluetoothProfileManager {
+ private static final String TAG = "LocalBluetoothProfileManager";
+ private static final boolean DEBUG = Utils.D;
+ /** Singleton instance. */
+ private static LocalBluetoothProfileManager sInstance;
+
+ /**
+ * An interface for notifying BluetoothHeadset IPC clients when they have
+ * been connected to the BluetoothHeadset service.
+ * Only used by com.android.settings.bluetooth.DockService.
+ */
+ public interface ServiceListener {
+ /**
+ * Called to notify the client when this proxy object has been
+ * connected to the BluetoothHeadset service. Clients must wait for
+ * this callback before making IPC calls on the BluetoothHeadset
+ * service.
+ */
+ void onServiceConnected();
+
+ /**
+ * Called to notify the client that this proxy object has been
+ * disconnected from the BluetoothHeadset service. Clients must not
+ * make IPC calls on the BluetoothHeadset service after this callback.
+ * This callback will currently only occur if the application hosting
+ * the BluetoothHeadset service, but may be called more often in future.
+ */
+ void onServiceDisconnected();
+ }
+
+ private final Context mContext;
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final BluetoothEventManager mEventManager;
+
+ private A2dpProfile mA2dpProfile;
+ private HeadsetProfile mHeadsetProfile;
+ private MapProfile mMapProfile;
+ private final HidProfile mHidProfile;
+ private OppProfile mOppProfile;
+ private final PanProfile mPanProfile;
+ private final PbapServerProfile mPbapProfile;
+
+ /**
+ * Mapping from profile name, e.g. "HEADSET" to profile object.
+ */
+ private final Map<String, LocalBluetoothProfile>
+ mProfileNameMap = new HashMap<String, LocalBluetoothProfile>();
+
+ LocalBluetoothProfileManager(Context context,
+ LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ BluetoothEventManager eventManager) {
+ mContext = context;
+
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mEventManager = eventManager;
+ // pass this reference to adapter and event manager (circular dependency)
+ mLocalAdapter.setProfileManager(this);
+ mEventManager.setProfileManager(this);
+
+ ParcelUuid[] uuids = adapter.getUuids();
+
+ // uuids may be null if Bluetooth is turned off
+ if (uuids != null) {
+ updateLocalProfiles(uuids);
+ }
+
+ // Always add HID and PAN profiles
+ mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
+ addProfile(mHidProfile, HidProfile.NAME,
+ BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
+
+ mPanProfile = new PanProfile(context);
+ addPanProfile(mPanProfile, PanProfile.NAME,
+ BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
+
+ if(DEBUG) Log.d(TAG, "Adding local MAP profile");
+ mMapProfile = new MapProfile(mContext, mLocalAdapter,
+ mDeviceManager, this);
+ addProfile(mMapProfile, MapProfile.NAME,
+ BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
+
+ //Create PBAP server profile, but do not add it to list of profiles
+ // as we do not need to monitor the profile as part of profile list
+ mPbapProfile = new PbapServerProfile(context);
+
+ if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
+ }
+
+ /**
+ * Initialize or update the local profile objects. If a UUID was previously
+ * present but has been removed, we print a warning but don't remove the
+ * profile object as it might be referenced elsewhere, or the UUID might
+ * come back and we don't want multiple copies of the profile objects.
+ * @param uuids
+ */
+ void updateLocalProfiles(ParcelUuid[] uuids) {
+ // A2DP
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
+ if (mA2dpProfile == null) {
+ if(DEBUG) Log.d(TAG, "Adding local A2DP profile");
+ mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mA2dpProfile, A2dpProfile.NAME,
+ BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+ }
+ } else if (mA2dpProfile != null) {
+ Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
+ }
+
+ // Headset / Handsfree
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
+ BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
+ if (mHeadsetProfile == null) {
+ if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
+ mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
+ mDeviceManager, this);
+ addProfile(mHeadsetProfile, HeadsetProfile.NAME,
+ BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+ }
+ } else if (mHeadsetProfile != null) {
+ Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
+ }
+
+ // OPP
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
+ if (mOppProfile == null) {
+ if(DEBUG) Log.d(TAG, "Adding local OPP profile");
+ mOppProfile = new OppProfile();
+ // Note: no event handler for OPP, only name map.
+ mProfileNameMap.put(OppProfile.NAME, mOppProfile);
+ }
+ } else if (mOppProfile != null) {
+ Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
+ }
+ mEventManager.registerProfileIntentReceiver();
+
+ // There is no local SDP record for HID and Settings app doesn't control PBAP
+ }
+
+ private final Collection<ServiceListener> mServiceListeners =
+ new ArrayList<ServiceListener>();
+
+ private void addProfile(LocalBluetoothProfile profile,
+ String profileName, String stateChangedAction) {
+ mEventManager.addProfileHandler(stateChangedAction, new StateChangedHandler(profile));
+ mProfileNameMap.put(profileName, profile);
+ }
+
+ private void addPanProfile(LocalBluetoothProfile profile,
+ String profileName, String stateChangedAction) {
+ mEventManager.addProfileHandler(stateChangedAction,
+ new PanStateChangedHandler(profile));
+ mProfileNameMap.put(profileName, profile);
+ }
+
+ public LocalBluetoothProfile getProfileByName(String name) {
+ return mProfileNameMap.get(name);
+ }
+
+ // Called from LocalBluetoothAdapter when state changes to ON
+ void setBluetoothStateOn() {
+ ParcelUuid[] uuids = mLocalAdapter.getUuids();
+ if (uuids != null) {
+ updateLocalProfiles(uuids);
+ }
+ mEventManager.readPairedDevices();
+ }
+
+ /**
+ * Generic handler for connection state change events for the specified profile.
+ */
+ private class StateChangedHandler implements BluetoothEventManager.Handler {
+ final LocalBluetoothProfile mProfile;
+
+ StateChangedHandler(LocalBluetoothProfile profile) {
+ mProfile = profile;
+ }
+
+ public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+ CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+ if (cachedDevice == null) {
+ Log.w(TAG, "StateChangedHandler found new device: " + device);
+ cachedDevice = mDeviceManager.addDevice(mLocalAdapter,
+ LocalBluetoothProfileManager.this, device);
+ }
+ int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
+ int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
+ if (newState == BluetoothProfile.STATE_DISCONNECTED &&
+ oldState == BluetoothProfile.STATE_CONNECTING) {
+ Log.i(TAG, "Failed to connect " + mProfile + " device");
+ }
+
+ cachedDevice.onProfileStateChanged(mProfile, newState);
+ cachedDevice.refresh();
+ }
+ }
+
+ /** State change handler for NAP and PANU profiles. */
+ private class PanStateChangedHandler extends StateChangedHandler {
+
+ PanStateChangedHandler(LocalBluetoothProfile profile) {
+ super(profile);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+ PanProfile panProfile = (PanProfile) mProfile;
+ int role = intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, 0);
+ panProfile.setLocalRole(device, role);
+ super.onReceive(context, intent, device);
+ }
+ }
+
+ // called from DockService
+ public void addServiceListener(ServiceListener l) {
+ mServiceListeners.add(l);
+ }
+
+ // called from DockService
+ public void removeServiceListener(ServiceListener l) {
+ mServiceListeners.remove(l);
+ }
+
+ // not synchronized: use only from UI thread! (TODO: verify)
+ void callServiceConnectedListeners() {
+ for (ServiceListener l : mServiceListeners) {
+ l.onServiceConnected();
+ }
+ }
+
+ // not synchronized: use only from UI thread! (TODO: verify)
+ void callServiceDisconnectedListeners() {
+ for (ServiceListener listener : mServiceListeners) {
+ listener.onServiceDisconnected();
+ }
+ }
+
+ // This is called by DockService, so check Headset and A2DP.
+ public synchronized boolean isManagerReady() {
+ // Getting just the headset profile is fine for now. Will need to deal with A2DP
+ // and others if they aren't always in a ready state.
+ LocalBluetoothProfile profile = mHeadsetProfile;
+ if (profile != null) {
+ return profile.isProfileReady();
+ }
+ profile = mA2dpProfile;
+ if (profile != null) {
+ return profile.isProfileReady();
+ }
+ return false;
+ }
+
+ public A2dpProfile getA2dpProfile() {
+ return mA2dpProfile;
+ }
+
+ public HeadsetProfile getHeadsetProfile() {
+ return mHeadsetProfile;
+ }
+
+ public PbapServerProfile getPbapProfile(){
+ return mPbapProfile;
+ }
+
+ public MapProfile getMapProfile(){
+ return mMapProfile;
+ }
+
+ /**
+ * Fill in a list of LocalBluetoothProfile objects that are supported by
+ * the local device and the remote device.
+ *
+ * @param uuids of the remote device
+ * @param localUuids UUIDs of the local device
+ * @param profiles The list of profiles to fill
+ * @param removedProfiles list of profiles that were removed
+ */
+ synchronized void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids,
+ Collection<LocalBluetoothProfile> profiles,
+ Collection<LocalBluetoothProfile> removedProfiles,
+ boolean isPanNapConnected, BluetoothDevice device) {
+ // Copy previous profile list into removedProfiles
+ removedProfiles.clear();
+ removedProfiles.addAll(profiles);
+ profiles.clear();
+
+ if (uuids == null) {
+ return;
+ }
+
+ if (mHeadsetProfile != null) {
+ if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) &&
+ BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) ||
+ (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) &&
+ BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) {
+ profiles.add(mHeadsetProfile);
+ removedProfiles.remove(mHeadsetProfile);
+ }
+ }
+
+ if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) &&
+ mA2dpProfile != null) {
+ profiles.add(mA2dpProfile);
+ removedProfiles.remove(mA2dpProfile);
+ }
+
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) &&
+ mOppProfile != null) {
+ profiles.add(mOppProfile);
+ removedProfiles.remove(mOppProfile);
+ }
+
+ if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) ||
+ BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) &&
+ mHidProfile != null) {
+ profiles.add(mHidProfile);
+ removedProfiles.remove(mHidProfile);
+ }
+
+ if(isPanNapConnected)
+ if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists.");
+ if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) &&
+ mPanProfile != null) || isPanNapConnected) {
+ profiles.add(mPanProfile);
+ removedProfiles.remove(mPanProfile);
+ }
+
+ if ((mMapProfile != null) &&
+ (mMapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) {
+ profiles.add(mMapProfile);
+ removedProfiles.remove(mMapProfile);
+ mMapProfile.setPreferred(device, true);
+ }
+ }
+
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
new file mode 100644
index 0000000..e6a152f
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMap;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MapProfile handles Bluetooth MAP profile.
+ */
+public final class MapProfile implements LocalBluetoothProfile {
+ private static final String TAG = "MapProfile";
+ private static boolean V = true;
+
+ private BluetoothMap mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ static final ParcelUuid[] UUIDS = {
+ BluetoothUuid.MAP,
+ BluetoothUuid.MNS,
+ BluetoothUuid.MAS,
+ };
+
+ static final String NAME = "MAP";
+
+ // Order of this profile in device profiles list
+
+ // These callbacks run on the main thread.
+ private final class MapServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothMap) proxy;
+ // We just bound to the service, so refresh the UI for any connected MAP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "MapProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(MapProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+
+ mProfileManager.callServiceConnectedListeners();
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mProfileManager.callServiceDisconnectedListeners();
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+ return mIsProfileReady;
+ }
+
+ MapProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new MapServiceListener(),
+ BluetoothProfile.MAP);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if(V)Log.d(TAG,"connect() - should not get called");
+ return false; // MAP never connects out
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ } else {
+ return false;
+ }
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if(V) Log.d(TAG,"getConnectionStatus: status is: "+ mService.getConnectionState(device));
+
+ return !deviceList.isEmpty() && deviceList.get(0).equals(device)
+ ? mService.getConnectionState(device)
+ : BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return BluetoothProfile.MAP;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_map;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_map_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_map_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_cellphone;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up MAP proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
new file mode 100755
index 0000000..31e675c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import com.android.settingslib.R;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+
+/**
+ * OppProfile handles Bluetooth OPP.
+ */
+final class OppProfile implements LocalBluetoothProfile {
+
+ static final String NAME = "OPP";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 2;
+
+ public boolean isConnectable() {
+ return false;
+ }
+
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ return false;
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ return false;
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ return BluetoothProfile.STATE_DISCONNECTED; // Settings app doesn't handle OPP
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ return false;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ return BluetoothProfile.PRIORITY_OFF; // Settings app doesn't handle OPP
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ }
+
+ public boolean isProfileReady() {
+ return true;
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_opp;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ return 0; // OPP profile not displayed in UI
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return 0; // no icon for OPP
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
new file mode 100755
index 0000000..3af89e6
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * PanProfile handles Bluetooth PAN profile (NAP and PANU).
+ */
+final class PanProfile implements LocalBluetoothProfile {
+ private static final String TAG = "PanProfile";
+ private static boolean V = true;
+
+ private BluetoothPan mService;
+ private boolean mIsProfileReady;
+
+ // Tethering direction for each device
+ private final HashMap<BluetoothDevice, Integer> mDeviceRoleMap =
+ new HashMap<BluetoothDevice, Integer>();
+
+ static final String NAME = "PAN";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 4;
+
+ // These callbacks run on the main thread.
+ private final class PanServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothPan) proxy;
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ PanProfile(Context context) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ adapter.getProfileProxy(context, new PanServiceListener(),
+ BluetoothProfile.PAN);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> sinks = mService.getConnectedDevices();
+ if (sinks != null) {
+ for (BluetoothDevice sink : sinks) {
+ mService.disconnect(sink);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ // return current connection status so profile checkbox is set correctly
+ return getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ return -1;
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ // ignore: isPreferred is always true for PAN
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ if (isLocalRoleNap(device)) {
+ return R.string.bluetooth_profile_pan_nap;
+ } else {
+ return R.string.bluetooth_profile_pan;
+ }
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_pan_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ if (isLocalRoleNap(device)) {
+ return R.string.bluetooth_pan_nap_profile_summary_connected;
+ } else {
+ return R.string.bluetooth_pan_user_profile_summary_connected;
+ }
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_network_pan;
+ }
+
+ // Tethering direction determines UI strings.
+ void setLocalRole(BluetoothDevice device, int role) {
+ mDeviceRoleMap.put(device, role);
+ }
+
+ boolean isLocalRoleNap(BluetoothDevice device) {
+ if (mDeviceRoleMap.containsKey(device)) {
+ return mDeviceRoleMap.get(device) == BluetoothPan.LOCAL_NAP_ROLE;
+ } else {
+ return false;
+ }
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.PAN, mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up PAN proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
new file mode 100755
index 0000000..a552b24a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPbap;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * PBAPServer Profile
+ */
+public final class PbapServerProfile implements LocalBluetoothProfile {
+ private static final String TAG = "PbapServerProfile";
+ private static boolean V = true;
+
+ private BluetoothPbap mService;
+ private boolean mIsProfileReady;
+
+ static final String NAME = "PBAP Server";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 6;
+
+ // The UUIDs indicate that remote device might access pbap server
+ static final ParcelUuid[] PBAB_CLIENT_UUIDS = {
+ BluetoothUuid.HSP,
+ BluetoothUuid.Handsfree,
+ BluetoothUuid.PBAP_PCE
+ };
+
+ // These callbacks run on the main thread.
+ private final class PbapServiceListener
+ implements BluetoothPbap.ServiceListener {
+
+ public void onServiceConnected(BluetoothPbap proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothPbap) proxy;
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected() {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ PbapServerProfile(Context context) {
+ BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener());
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return false;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ /*Can't connect from server */
+ return false;
+
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.disconnect();
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ if (mService.isConnected(device))
+ return BluetoothProfile.STATE_CONNECTED;
+ else
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ return false;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ return -1;
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ // ignore: isPreferred is always true for PBAP
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_pbap;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ return R.string.bluetooth_profile_pbap_summary;
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_cellphone;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ mService.close();
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up PBAP proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/Utils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/Utils.java
new file mode 100644
index 0000000..c919426
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/Utils.java
@@ -0,0 +1,43 @@
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+
+public class Utils {
+ public static final boolean V = false; // verbose logging
+ public static final boolean D = true; // regular logging
+
+ private static ErrorListener sErrorListener;
+
+ public static int getConnectionStateSummary(int connectionState) {
+ switch (connectionState) {
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_connected;
+ case BluetoothProfile.STATE_CONNECTING:
+ return R.string.bluetooth_connecting;
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_disconnected;
+ case BluetoothProfile.STATE_DISCONNECTING:
+ return R.string.bluetooth_disconnecting;
+ default:
+ return 0;
+ }
+ }
+
+ static void showError(Context context, String name, int messageResId) {
+ if (sErrorListener != null) {
+ sErrorListener.onShowError(context, name, messageResId);
+ }
+ }
+
+ public static void setErrorListener(ErrorListener listener) {
+ sErrorListener = listener;
+ }
+
+ public interface ErrorListener {
+ void onShowError(Context context, String name, int messageResId);
+ }
+
+}
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index c16f7b6..2b833b2 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -3,7 +3,8 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-subdir-java-files) \
+ src/com/android/providers/settings/EventLogTags.logtags
LOCAL_JAVA_LIBRARIES := telephony-common ims-common
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 06e26bd..729efcb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -58,6 +58,7 @@
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Database helper class for {@link SettingsProvider}.
@@ -78,6 +79,9 @@
private static final HashSet<String> mValidTables = new HashSet<String>();
+ private static final String DATABASE_JOURNAL_SUFFIX = "-journal";
+ private static final String DATABASE_BACKUP_SUFFIX = "-backup";
+
private static final String TABLE_SYSTEM = "system";
private static final String TABLE_SECURE = "secure";
private static final String TABLE_GLOBAL = "global";
@@ -86,13 +90,13 @@
mValidTables.add(TABLE_SYSTEM);
mValidTables.add(TABLE_SECURE);
mValidTables.add(TABLE_GLOBAL);
- mValidTables.add("bluetooth_devices");
- mValidTables.add("bookmarks");
// These are old.
+ mValidTables.add("bluetooth_devices");
+ mValidTables.add("bookmarks");
mValidTables.add("favorites");
- mValidTables.add("gservices");
mValidTables.add("old_favorites");
+ mValidTables.add("android_metadata");
}
static String dbNameForUser(final int userHandle) {
@@ -118,6 +122,33 @@
return mValidTables.contains(name);
}
+ public void dropDatabase() {
+ close();
+ File databaseFile = mContext.getDatabasePath(getDatabaseName());
+ if (databaseFile.exists()) {
+ databaseFile.delete();
+ }
+ File databaseJournalFile = mContext.getDatabasePath(getDatabaseName()
+ + DATABASE_JOURNAL_SUFFIX);
+ if (databaseJournalFile.exists()) {
+ databaseJournalFile.delete();
+ }
+ }
+
+ public void backupDatabase() {
+ close();
+ File databaseFile = mContext.getDatabasePath(getDatabaseName());
+ if (!databaseFile.exists()) {
+ return;
+ }
+ File backupFile = mContext.getDatabasePath(getDatabaseName()
+ + DATABASE_BACKUP_SUFFIX);
+ if (backupFile.exists()) {
+ return;
+ }
+ databaseFile.renameTo(backupFile);
+ }
+
private void createSecureTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE secure (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
@@ -1221,9 +1252,11 @@
// Migrate now-global settings. Note that this happens before
// new users can be created.
createGlobalTable(db);
- String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
+ String[] settingsToMove = setToStringArray(
+ SettingsProvider.sSystemMovedToGlobalSettings);
moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, false);
- settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
+ settingsToMove = setToStringArray(
+ SettingsProvider.sSecureMovedToGlobalSettings);
moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, false);
db.setTransactionSuccessful();
@@ -1489,9 +1522,11 @@
db.beginTransaction();
try {
// Migrate now-global settings
- String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
+ String[] settingsToMove = setToStringArray(
+ SettingsProvider.sSystemMovedToGlobalSettings);
moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
- settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
+ settingsToMove = setToStringArray(
+ SettingsProvider.sSecureMovedToGlobalSettings);
moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
db.setTransactionSuccessful();
@@ -1855,7 +1890,8 @@
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+ " VALUES(?,?);");
- loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
+ loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,
+ ImsConfig.FeatureValueConstants.ON);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -1895,34 +1931,50 @@
}
upgradeVersion = 118;
}
+
+ /**
+ * IMPORTANT: Do not add any more upgrade steps here as the global,
+ * secure, and system settings are no longer stored in a database
+ * but are kept in memory and persisted to XML. The correct places
+ * for adding upgrade steps are:
+ *
+ * Global: SettingsProvider.UpgradeController#onUpgradeGlobalSettings
+ * Secure: SettingsProvider.UpgradeController#onUpgradeSecureSettings
+ * System: SettingsProvider.UpgradeController#onUpgradeSystemSettings
+ */
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
- Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
- + ", must wipe the settings provider");
- db.execSQL("DROP TABLE IF EXISTS global");
- db.execSQL("DROP TABLE IF EXISTS globalIndex1");
- db.execSQL("DROP TABLE IF EXISTS system");
- db.execSQL("DROP INDEX IF EXISTS systemIndex1");
- db.execSQL("DROP TABLE IF EXISTS secure");
- db.execSQL("DROP INDEX IF EXISTS secureIndex1");
- db.execSQL("DROP TABLE IF EXISTS gservices");
- db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
- db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
- db.execSQL("DROP TABLE IF EXISTS bookmarks");
- db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
- db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
- db.execSQL("DROP TABLE IF EXISTS favorites");
- onCreate(db);
-
- // Added for diagnosing settings.db wipes after the fact
- String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
- db.execSQL("INSERT INTO secure(name,value) values('" +
- "wiped_db_reason" + "','" + wipeReason + "');");
+ recreateDatabase(db, oldVersion, upgradeVersion, currentVersion);
}
}
- private String[] hashsetToStringArray(HashSet<String> set) {
+ public void recreateDatabase(SQLiteDatabase db, int oldVersion,
+ int upgradeVersion, int currentVersion) {
+ db.execSQL("DROP TABLE IF EXISTS global");
+ db.execSQL("DROP TABLE IF EXISTS globalIndex1");
+ db.execSQL("DROP TABLE IF EXISTS system");
+ db.execSQL("DROP INDEX IF EXISTS systemIndex1");
+ db.execSQL("DROP TABLE IF EXISTS secure");
+ db.execSQL("DROP INDEX IF EXISTS secureIndex1");
+ db.execSQL("DROP TABLE IF EXISTS gservices");
+ db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
+ db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
+ db.execSQL("DROP TABLE IF EXISTS bookmarks");
+ db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
+ db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
+ db.execSQL("DROP TABLE IF EXISTS favorites");
+
+ onCreate(db);
+
+ // Added for diagnosing settings.db wipes after the fact
+ String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
+ db.execSQL("INSERT INTO secure(name,value) values('" +
+ "wiped_db_reason" + "','" + wipeReason + "');");
+ }
+
+ private String[] setToStringArray(Set<String> set) {
String[] array = new String[set.size()];
return set.toArray(array);
}
@@ -2639,7 +2691,8 @@
loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
R.bool.def_guest_user_enabled);
- loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
+ loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED,
+ ImsConfig.FeatureValueConstants.ON);
// --- New global settings start here
} finally {
if (stmt != null) stmt.close();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags b/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags
new file mode 100644
index 0000000..298d776
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags
@@ -0,0 +1,5 @@
+# See system/core/logcat/e for a description of the format of this file.
+
+option java_package com.android.providers.settings;
+
+52100 unsupported_settings_query (uri|3),(selection|3),(whereArgs|3)
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 264dcae..eac83d8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -32,14 +32,18 @@
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
+import com.android.internal.widget.LockPatternUtils;
+
import libcore.io.IoUtils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.DataInputStream;
@@ -76,10 +80,11 @@
private static final String KEY_SECURE = "secure";
private static final String KEY_GLOBAL = "global";
private static final String KEY_LOCALE = "locale";
+ private static final String KEY_LOCK_SETTINGS = "lock_settings";
// Versioning of the state file. Increment this version
// number any time the set of state items is altered.
- private static final int STATE_VERSION = 3;
+ private static final int STATE_VERSION = 4;
// Slots in the checksum array. Never insert new items in the middle
// of this array; new slots must be appended.
@@ -89,20 +94,23 @@
private static final int STATE_WIFI_SUPPLICANT = 3;
private static final int STATE_WIFI_CONFIG = 4;
private static final int STATE_GLOBAL = 5;
+ private static final int STATE_LOCK_SETTINGS = 6;
- private static final int STATE_SIZE = 6; // The current number of state items
+ private static final int STATE_SIZE = 7; // The current number of state items
// Number of entries in the checksum array at various version numbers
private static final int STATE_SIZES[] = {
0,
4, // version 1
5, // version 2 added STATE_WIFI_CONFIG
- STATE_SIZE // version 3 added STATE_GLOBAL
+ 6, // version 3 added STATE_GLOBAL
+ STATE_SIZE // version 4 added STATE_LOCK_SETTINGS
};
// Versioning of the 'full backup' format
- private static final int FULL_BACKUP_VERSION = 2;
+ private static final int FULL_BACKUP_VERSION = 3;
private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry
+ private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
@@ -110,11 +118,7 @@
private static final String TAG = "SettingsBackupAgent";
- private static final int COLUMN_NAME = 1;
- private static final int COLUMN_VALUE = 2;
-
private static final String[] PROJECTION = {
- Settings.NameValueTable._ID,
Settings.NameValueTable.NAME,
Settings.NameValueTable.VALUE
};
@@ -128,6 +132,10 @@
private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI";
private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI";
+ // Keys within the lock settings section
+ private static final String KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED = "owner_info_enabled";
+ private static final String KEY_LOCK_SETTINGS_OWNER_INFO = "owner_info";
+
// Name of the temporary file we use during full backup/restore. This is
// stored in the full-backup tarfile as well, so should not be changed.
private static final String STAGE_FILE = "flattened-data";
@@ -371,6 +379,7 @@
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
+ byte[] lockSettingsData = getLockSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -391,6 +400,9 @@
stateChecksums[STATE_WIFI_CONFIG] =
writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
data);
+ stateChecksums[STATE_LOCK_SETTINGS] =
+ writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
+ lockSettingsData, data);
writeNewChecksums(stateChecksums, newState);
}
@@ -473,8 +485,8 @@
ParcelFileDescriptor newState) throws IOException {
HashSet<String> movedToGlobal = new HashSet<String>();
- Settings.System.getMovedKeys(movedToGlobal);
- Settings.Secure.getMovedKeys(movedToGlobal);
+ Settings.System.getMovedToGlobalSettings(movedToGlobal);
+ Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
while (data.readNextHeader()) {
final String key = data.getKey();
@@ -496,6 +508,8 @@
} else if (KEY_WIFI_CONFIG.equals(key)) {
initWifiRestoreIfNecessary();
mWifiRestore.incorporateWifiConfigFile(data);
+ } else if (KEY_LOCK_SETTINGS.equals(key)) {
+ restoreLockSettings(data);
} else {
data.skipEntityData();
}
@@ -517,6 +531,7 @@
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
+ byte[] lockSettingsData = getLockSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
@@ -551,6 +566,9 @@
if (DEBUG_BACKUP) Log.d(TAG, wifiConfigData.length + " bytes of wifi config data");
out.writeInt(wifiConfigData.length);
out.write(wifiConfigData);
+ if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
+ out.writeInt(lockSettingsData.length);
+ out.write(lockSettingsData);
out.flush(); // also flushes downstream
@@ -577,8 +595,8 @@
if (version <= FULL_BACKUP_VERSION) {
// Generate the moved-to-global lookup table
HashSet<String> movedToGlobal = new HashSet<String>();
- Settings.System.getMovedKeys(movedToGlobal);
- Settings.Secure.getMovedKeys(movedToGlobal);
+ Settings.System.getMovedToGlobalSettings(movedToGlobal);
+ Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
// system settings data first
int nBytes = in.readInt();
@@ -633,6 +651,16 @@
in.readFully(buffer, 0, nBytes);
restoreFileData(mWifiConfigFile, buffer, nBytes);
+ if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) {
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of lock settings data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ if (nBytes > 0) {
+ in.readFully(buffer, 0, nBytes);
+ restoreLockSettings(buffer, nBytes);
+ }
+ }
+
if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
} else {
data.close();
@@ -680,6 +708,9 @@
return oldChecksum;
}
try {
+ if (DEBUG_BACKUP) {
+ Log.v(TAG, "Writing entity " + key + " of size " + data.length);
+ }
output.writeEntityHeader(key, data.length);
output.writeEntityData(data, data.length);
} catch (IOException ioe) {
@@ -718,6 +749,31 @@
}
}
+ /**
+ * Serialize the owner info settings
+ */
+ private byte[] getLockSettings() {
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+ final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled();
+ final String ownerInfo = lockPatternUtils.getOwnerInfo(UserHandle.myUserId());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+ try {
+ out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED);
+ out.writeUTF(ownerInfoEnabled ? "1" : "0");
+ if (ownerInfo != null) {
+ out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO);
+ out.writeUTF(ownerInfo != null ? ownerInfo : "");
+ }
+ // End marker
+ out.writeUTF("");
+ out.flush();
+ } catch (IOException ioe) {
+ }
+ return baos.toByteArray();
+ }
+
private void restoreSettings(BackupDataInput data, Uri contentUri,
HashSet<String> movedToGlobal) {
byte[] settings = new byte[data.getDataSize()];
@@ -801,6 +857,50 @@
}
/**
+ * Restores the owner info enabled and owner info settings in LockSettings.
+ *
+ * @param buffer
+ * @param nBytes
+ */
+ private void restoreLockSettings(byte[] buffer, int nBytes) {
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes);
+ DataInputStream in = new DataInputStream(bais);
+ try {
+ String key;
+ // Read until empty string marker
+ while ((key = in.readUTF()).length() > 0) {
+ final String value = in.readUTF();
+ if (DEBUG_BACKUP) {
+ Log.v(TAG, "Restoring lock_settings " + key + " = " + value);
+ }
+ switch (key) {
+ case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED:
+ lockPatternUtils.setOwnerInfoEnabled("1".equals(value));
+ break;
+ case KEY_LOCK_SETTINGS_OWNER_INFO:
+ lockPatternUtils.setOwnerInfo(value, UserHandle.myUserId());
+ break;
+ }
+ }
+ in.close();
+ } catch (IOException ioe) {
+ }
+ }
+
+ private void restoreLockSettings(BackupDataInput data) {
+ final byte[] settings = new byte[data.getDataSize()];
+ try {
+ data.readEntityData(settings, 0, settings.length);
+ } catch (IOException ioe) {
+ Log.e(TAG, "Couldn't read entity data");
+ return;
+ }
+ restoreLockSettings(settings, settings.length);
+ }
+
+ /**
* Given a cursor and a set of keys, extract the required keys and
* values and write them to a byte array.
*
@@ -824,11 +924,14 @@
String key = settings[i];
String value = cachedEntries.remove(key);
+ final int nameColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.NAME);
+ final int valueColumnIndex = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+
// If the value not cached, let us look it up.
if (value == null) {
while (!cursor.isAfterLast()) {
- String cursorKey = cursor.getString(COLUMN_NAME);
- String cursorValue = cursor.getString(COLUMN_VALUE);
+ String cursorKey = cursor.getString(nameColumnIndex);
+ String cursorValue = cursor.getString(valueColumnIndex);
cursor.moveToNext();
if (key.equals(cursorKey)) {
value = cursorValue;
@@ -942,6 +1045,7 @@
ByteArrayOutputStream bos = new ByteArrayOutputStream();
OutputStreamWriter out = new OutputStreamWriter(bos);
fromFile.write(out);
+ out.flush();
return bos.toByteArray();
} else {
return EMPTY_DATA;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6828301..2c63647 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -16,1211 +16,463 @@
package com.android.providers.settings;
-import java.io.FileNotFoundException;
-import java.security.SecureRandom;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
+import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
-import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
-import android.database.AbstractCursor;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteQueryBuilder;
+import android.hardware.camera2.utils.ArrayUtils;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager;
-import android.os.FileObserver;
+import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.text.TextUtils;
-import android.util.Log;
-import android.util.LruCache;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.BackgroundThread;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import com.android.providers.settings.SettingsState.Setting;
+
+/**
+ * <p>
+ * This class is a content provider that publishes the system settings.
+ * It can be accessed via the content provider APIs or via custom call
+ * commands. The latter is a bit faster and is the preferred way to access
+ * the platform settings.
+ * </p>
+ * <p>
+ * There are three settings types, global (with signature level protection
+ * and shared across users), secure (with signature permission level
+ * protection and per user), and system (with dangerous permission level
+ * protection and per user). Global settings are stored under the device owner.
+ * Each of these settings is represented by a {@link
+ * com.android.providers.settings.SettingsState} object mapped to an integer
+ * key derived from the setting type in the most significant bits and user
+ * id in the least significant bits. Settings are synchronously loaded on
+ * instantiation of a SettingsState and asynchronously persisted on mutation.
+ * Settings are stored in the user specific system directory.
+ * </p>
+ * <p>
+ * Apps targeting APIs Lollipop MR1 and lower can add custom settings entries
+ * and get a warning. Targeting higher API version prohibits this as the
+ * system settings are not a place for apps to save their state. When a package
+ * is removed the settings it added are deleted. Apps cannot delete system
+ * settings added by the platform. System settings values are validated to
+ * ensure the clients do not put bad values. Global and secure settings are
+ * changed only by trusted parties, therefore no validation is performed. Also
+ * there is a limit on the amount of app specific settings that can be added
+ * to prevent unlimited growth of the system process memory footprint.
+ * </p>
+ */
+@SuppressWarnings("deprecation")
public class SettingsProvider extends ContentProvider {
- private static final String TAG = "SettingsProvider";
- private static final boolean LOCAL_LOGV = false;
+ private static final boolean DEBUG = false;
- private static final boolean USER_CHECK_THROWS = true;
+ private static final boolean DROP_DATABASE_ON_MIGRATION = !Build.IS_DEBUGGABLE;
+
+ private static final String LOG_TAG = "SettingsProvider";
private static final String TABLE_SYSTEM = "system";
private static final String TABLE_SECURE = "secure";
private static final String TABLE_GLOBAL = "global";
+
+ // Old tables no longer exist.
private static final String TABLE_FAVORITES = "favorites";
private static final String TABLE_OLD_FAVORITES = "old_favorites";
+ private static final String TABLE_BLUETOOTH_DEVICES = "bluetooth_devices";
+ private static final String TABLE_BOOKMARKS = "bookmarks";
+ private static final String TABLE_ANDROID_METADATA = "android_metadata";
- private static final String[] COLUMN_VALUE = new String[] { "value" };
-
- // Caches for each user's settings, access-ordered for acting as LRU.
- // Guarded by themselves.
- private static final int MAX_CACHE_ENTRIES = 200;
- private static final SparseArray<SettingsCache> sSystemCaches
- = new SparseArray<SettingsCache>();
- private static final SparseArray<SettingsCache> sSecureCaches
- = new SparseArray<SettingsCache>();
- private static final SettingsCache sGlobalCache = new SettingsCache(TABLE_GLOBAL);
-
- // The count of how many known (handled by SettingsProvider)
- // database mutations are currently being handled for this user.
- // Used by file observers to not reload the database when it's ourselves
- // modifying it.
- private static final SparseArray<AtomicInteger> sKnownMutationsInFlight
- = new SparseArray<AtomicInteger>();
-
- // Each defined user has their own settings
- protected final SparseArray<DatabaseHelper> mOpenHelpers = new SparseArray<DatabaseHelper>();
-
- // Keep the list of managed profiles synced here
- private List<UserInfo> mManagedProfiles = null;
-
- // Over this size we don't reject loading or saving settings but
- // we do consider them broken/malicious and don't keep them in
- // memory at least:
- private static final int MAX_CACHE_ENTRY_SIZE = 500;
-
- private static final Bundle NULL_SETTING = Bundle.forPair("value", null);
-
- // Used as a sentinel value in an instance equality test when we
- // want to cache the existence of a key, but not store its value.
- private static final Bundle TOO_LARGE_TO_CACHE_MARKER = Bundle.forPair("_dummy", null);
-
- private UserManager mUserManager;
- private BackupManager mBackupManager;
-
- /**
- * Settings which need to be treated as global/shared in multi-user environments.
- */
- static final HashSet<String> sSecureGlobalKeys;
- static final HashSet<String> sSystemGlobalKeys;
-
- // Settings that cannot be modified if associated user restrictions are enabled.
- static final Map<String, String> sRestrictedKeys;
-
- private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
-
- static final HashSet<String> sSecureCloneToManagedKeys;
- static final HashSet<String> sSystemCloneToManagedKeys;
-
+ // The set of removed legacy tables.
+ private static final Set<String> REMOVED_LEGACY_TABLES = new ArraySet<>();
static {
- // Keys (name column) from the 'secure' table that are now in the owner user's 'global'
- // table, shared across all users
- // These must match Settings.Secure.MOVED_TO_GLOBAL
- sSecureGlobalKeys = new HashSet<String>();
- Settings.Secure.getMovedKeys(sSecureGlobalKeys);
+ REMOVED_LEGACY_TABLES.add(TABLE_FAVORITES);
+ REMOVED_LEGACY_TABLES.add(TABLE_OLD_FAVORITES);
+ REMOVED_LEGACY_TABLES.add(TABLE_BLUETOOTH_DEVICES);
+ REMOVED_LEGACY_TABLES.add(TABLE_BOOKMARKS);
+ REMOVED_LEGACY_TABLES.add(TABLE_ANDROID_METADATA);
+ }
- // Keys from the 'system' table now moved to 'global'
- // These must match Settings.System.MOVED_TO_GLOBAL
- sSystemGlobalKeys = new HashSet<String>();
- Settings.System.getNonLegacyMovedKeys(sSystemGlobalKeys);
+ private static final int MUTATION_OPERATION_INSERT = 1;
+ private static final int MUTATION_OPERATION_DELETE = 2;
+ private static final int MUTATION_OPERATION_UPDATE = 3;
- sRestrictedKeys = new HashMap<String, String>();
- sRestrictedKeys.put(Settings.Secure.LOCATION_MODE, UserManager.DISALLOW_SHARE_LOCATION);
- sRestrictedKeys.put(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ private static final String[] ALL_COLUMNS = new String[] {
+ Settings.NameValueTable._ID,
+ Settings.NameValueTable.NAME,
+ Settings.NameValueTable.VALUE
+ };
+
+ private static final Bundle NULL_SETTING = Bundle.forPair(Settings.NameValueTable.VALUE, null);
+
+ // Per user settings that cannot be modified if associated user restrictions are enabled.
+ private static final Map<String, String> sSettingToUserRestrictionMap = new ArrayMap<>();
+ static {
+ sSettingToUserRestrictionMap.put(Settings.Secure.LOCATION_MODE,
UserManager.DISALLOW_SHARE_LOCATION);
- sRestrictedKeys.put(Settings.Secure.INSTALL_NON_MARKET_APPS,
+ sSettingToUserRestrictionMap.put(Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ UserManager.DISALLOW_SHARE_LOCATION);
+ sSettingToUserRestrictionMap.put(Settings.Secure.INSTALL_NON_MARKET_APPS,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
- sRestrictedKeys.put(Settings.Global.ADB_ENABLED, UserManager.DISALLOW_DEBUGGING_FEATURES);
- sRestrictedKeys.put(Settings.Global.PACKAGE_VERIFIER_ENABLE,
+ sSettingToUserRestrictionMap.put(Settings.Global.ADB_ENABLED,
+ UserManager.DISALLOW_DEBUGGING_FEATURES);
+ sSettingToUserRestrictionMap.put(Settings.Global.PACKAGE_VERIFIER_ENABLE,
UserManager.ENSURE_VERIFY_APPS);
- sRestrictedKeys.put(Settings.Global.PREFERRED_NETWORK_MODE,
+ sSettingToUserRestrictionMap.put(Settings.Global.PREFERRED_NETWORK_MODE,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
-
- sSecureCloneToManagedKeys = new HashSet<String>();
- for (int i = 0; i < Settings.Secure.CLONE_TO_MANAGED_PROFILE.length; i++) {
- sSecureCloneToManagedKeys.add(Settings.Secure.CLONE_TO_MANAGED_PROFILE[i]);
- }
- sSystemCloneToManagedKeys = new HashSet<String>();
- for (int i = 0; i < Settings.System.CLONE_TO_MANAGED_PROFILE.length; i++) {
- sSystemCloneToManagedKeys.add(Settings.System.CLONE_TO_MANAGED_PROFILE[i]);
- }
}
- private boolean settingMovedToGlobal(final String name) {
- return sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name);
+ // Per user secure settings that moved to the for all users global settings.
+ static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
+ static {
+ Settings.Secure.getMovedToGlobalSettings(sSecureMovedToGlobalSettings);
}
- /**
- * Decode a content URL into the table, projection, and arguments
- * used to access the corresponding database rows.
- */
- private static class SqlArguments {
- public String table;
- public final String where;
- public final String[] args;
-
- /** Operate on existing rows. */
- SqlArguments(Uri url, String where, String[] args) {
- if (url.getPathSegments().size() == 1) {
- // of the form content://settings/secure, arbitrary where clause
- this.table = url.getPathSegments().get(0);
- if (!DatabaseHelper.isValidTable(this.table)) {
- throw new IllegalArgumentException("Bad root path: " + this.table);
- }
- this.where = where;
- this.args = args;
- } else if (url.getPathSegments().size() != 2) {
- throw new IllegalArgumentException("Invalid URI: " + url);
- } else if (!TextUtils.isEmpty(where)) {
- throw new UnsupportedOperationException("WHERE clause not supported: " + url);
- } else {
- // of the form content://settings/secure/element_name, no where clause
- this.table = url.getPathSegments().get(0);
- if (!DatabaseHelper.isValidTable(this.table)) {
- throw new IllegalArgumentException("Bad root path: " + this.table);
- }
- if (TABLE_SYSTEM.equals(this.table) || TABLE_SECURE.equals(this.table) ||
- TABLE_GLOBAL.equals(this.table)) {
- this.where = Settings.NameValueTable.NAME + "=?";
- final String name = url.getPathSegments().get(1);
- this.args = new String[] { name };
- // Rewrite the table for known-migrated names
- if (TABLE_SYSTEM.equals(this.table) || TABLE_SECURE.equals(this.table)) {
- if (sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name)) {
- this.table = TABLE_GLOBAL;
- }
- }
- } else {
- // of the form content://bookmarks/19
- this.where = "_id=" + ContentUris.parseId(url);
- this.args = null;
- }
- }
- }
-
- /** Insert new rows (no where clause allowed). */
- SqlArguments(Uri url) {
- if (url.getPathSegments().size() == 1) {
- this.table = url.getPathSegments().get(0);
- if (!DatabaseHelper.isValidTable(this.table)) {
- throw new IllegalArgumentException("Bad root path: " + this.table);
- }
- this.where = null;
- this.args = null;
- } else {
- throw new IllegalArgumentException("Invalid URI: " + url);
- }
- }
+ // Per user system settings that moved to the for all users global settings.
+ static final Set<String> sSystemMovedToGlobalSettings = new ArraySet<>();
+ static {
+ Settings.System.getMovedToGlobalSettings(sSystemMovedToGlobalSettings);
}
- /**
- * Get the content URI of a row added to a table.
- * @param tableUri of the entire table
- * @param values found in the row
- * @param rowId of the row
- * @return the content URI for this particular row
- */
- private Uri getUriFor(Uri tableUri, ContentValues values, long rowId) {
- if (tableUri.getPathSegments().size() != 1) {
- throw new IllegalArgumentException("Invalid URI: " + tableUri);
- }
- String table = tableUri.getPathSegments().get(0);
- if (TABLE_SYSTEM.equals(table) ||
- TABLE_SECURE.equals(table) ||
- TABLE_GLOBAL.equals(table)) {
- String name = values.getAsString(Settings.NameValueTable.NAME);
- return Uri.withAppendedPath(tableUri, name);
- } else {
- return ContentUris.withAppendedId(tableUri, rowId);
- }
+ // Per user system settings that moved to the per user secure settings.
+ static final Set<String> sSystemMovedToSecureSettings = new ArraySet<>();
+ static {
+ Settings.System.getMovedToSecureSettings(sSystemMovedToSecureSettings);
}
- /**
- * Send a notification when a particular content URI changes.
- * Modify the system property used to communicate the version of
- * this table, for tables which have such a property. (The Settings
- * contract class uses these to provide client-side caches.)
- * @param uri to send notifications for
- */
- private void sendNotify(Uri uri, int userHandle) {
- // Update the system property *first*, so if someone is listening for
- // a notification and then using the contract class to get their data,
- // the system property will be updated and they'll get the new data.
-
- boolean backedUpDataChanged = false;
- String property = null, table = uri.getPathSegments().get(0);
- final boolean isGlobal = table.equals(TABLE_GLOBAL);
- if (table.equals(TABLE_SYSTEM)) {
- property = Settings.System.SYS_PROP_SETTING_VERSION;
- backedUpDataChanged = true;
- } else if (table.equals(TABLE_SECURE)) {
- property = Settings.Secure.SYS_PROP_SETTING_VERSION;
- backedUpDataChanged = true;
- } else if (isGlobal) {
- property = Settings.Global.SYS_PROP_SETTING_VERSION; // this one is global
- backedUpDataChanged = true;
- }
-
- if (property != null) {
- long version = SystemProperties.getLong(property, 0) + 1;
- if (LOCAL_LOGV) Log.v(TAG, "property: " + property + "=" + version);
- SystemProperties.set(property, Long.toString(version));
- }
-
- // Inform the backup manager about a data change
- if (backedUpDataChanged) {
- mBackupManager.dataChanged();
- }
- // Now send the notification through the content framework.
-
- String notify = uri.getQueryParameter("notify");
- if (notify == null || "true".equals(notify)) {
- final int notifyTarget = isGlobal ? UserHandle.USER_ALL : userHandle;
- final long oldId = Binder.clearCallingIdentity();
- try {
- getContext().getContentResolver().notifyChange(uri, null, true, notifyTarget);
- } finally {
- Binder.restoreCallingIdentity(oldId);
- }
- if (LOCAL_LOGV) Log.v(TAG, "notifying for " + notifyTarget + ": " + uri);
- } else {
- if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
- }
+ // Per all users global settings that moved to the per user secure settings.
+ static final Set<String> sGlobalMovedToSecureSettings = new ArraySet<>();
+ static {
+ Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings);
}
- /**
- * Make sure the caller has permission to write this data.
- * @param args supplied by the caller
- * @throws SecurityException if the caller is forbidden to write.
- */
- private void checkWritePermissions(SqlArguments args) {
- if ((TABLE_SECURE.equals(args.table) || TABLE_GLOBAL.equals(args.table)) &&
- getContext().checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- String.format("Permission denial: writing to secure settings requires %1$s",
- android.Manifest.permission.WRITE_SECURE_SETTINGS));
- }
+ // Per user secure settings that are cloned for the managed profiles of the user.
+ private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>();
+ static {
+ Settings.Secure.getCloneToManagedProfileSettings(sSecureCloneToManagedSettings);
}
- private void checkUserRestrictions(String setting, int userId) {
- String userRestriction = sRestrictedKeys.get(setting);
- if (!TextUtils.isEmpty(userRestriction)
- && mUserManager.hasUserRestriction(userRestriction, new UserHandle(userId))) {
- throw new SecurityException(
- "Permission denial: user is restricted from changing this setting.");
- }
+ // Per user system settings that are cloned for the managed profiles of the user.
+ private static final Set<String> sSystemCloneToManagedSettings = new ArraySet<>();
+ static {
+ Settings.System.getCloneToManagedProfileSettings(sSystemCloneToManagedSettings);
}
- // FileObserver for external modifications to the database file.
- // Note that this is for platform developers only with
- // userdebug/eng builds who should be able to tinker with the
- // sqlite database out from under the SettingsProvider, which is
- // normally the exclusive owner of the database. But we keep this
- // enabled all the time to minimize development-vs-user
- // differences in testing.
- private static SparseArray<SettingsFileObserver> sObserverInstances
- = new SparseArray<SettingsFileObserver>();
- private class SettingsFileObserver extends FileObserver {
- private final AtomicBoolean mIsDirty = new AtomicBoolean(false);
- private final int mUserHandle;
- private final String mPath;
+ private final Object mLock = new Object();
- public SettingsFileObserver(int userHandle, String path) {
- super(path, FileObserver.CLOSE_WRITE |
- FileObserver.CREATE | FileObserver.DELETE |
- FileObserver.MOVED_TO | FileObserver.MODIFY);
- mUserHandle = userHandle;
- mPath = path;
- }
+ @GuardedBy("mLock")
+ private SettingsRegistry mSettingsRegistry;
- public void onEvent(int event, String path) {
- final AtomicInteger mutationCount;
- synchronized (SettingsProvider.this) {
- mutationCount = sKnownMutationsInFlight.get(mUserHandle);
- }
- if (mutationCount != null && mutationCount.get() > 0) {
- // our own modification.
- return;
- }
- Log.d(TAG, "User " + mUserHandle + " external modification to " + mPath
- + "; event=" + event);
- if (!mIsDirty.compareAndSet(false, true)) {
- // already handled. (we get a few update events
- // during an sqlite write)
- return;
- }
- Log.d(TAG, "User " + mUserHandle + " updating our caches for " + mPath);
- fullyPopulateCaches(mUserHandle);
- mIsDirty.set(false);
- }
- }
+ @GuardedBy("mLock")
+ private UserManager mUserManager;
+
+ @GuardedBy("mLock")
+ private AppOpsManager mAppOpsManager;
+
+ @GuardedBy("mLock")
+ private PackageManager mPackageManager;
@Override
public boolean onCreate() {
- mBackupManager = new BackupManager(getContext());
- mUserManager = UserManager.get(getContext());
-
- setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
- establishDbTracking(UserHandle.USER_OWNER);
-
- IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_REMOVED);
- userFilter.addAction(Intent.ACTION_USER_ADDED);
- getContext().registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
- UserHandle.USER_OWNER);
- if (intent.getAction().equals(Intent.ACTION_USER_REMOVED)) {
- onUserRemoved(userHandle);
- } else if (intent.getAction().equals(Intent.ACTION_USER_ADDED)) {
- onProfilesChanged();
- }
- }
- }, userFilter);
-
- onProfilesChanged();
-
+ synchronized (mLock) {
+ mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ mAppOpsManager = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+ mPackageManager = getContext().getPackageManager();
+ mSettingsRegistry = new SettingsRegistry();
+ }
+ registerBroadcastReceivers();
return true;
}
- void onUserRemoved(int userHandle) {
- synchronized (this) {
- // the db file itself will be deleted automatically, but we need to tear down
- // our caches and other internal bookkeeping.
- FileObserver observer = sObserverInstances.get(userHandle);
- if (observer != null) {
- observer.stopWatching();
- sObserverInstances.delete(userHandle);
- }
-
- mOpenHelpers.delete(userHandle);
- sSystemCaches.delete(userHandle);
- sSecureCaches.delete(userHandle);
- sKnownMutationsInFlight.delete(userHandle);
- onProfilesChanged();
- }
- }
-
- /**
- * Updates the list of managed profiles. It assumes that only the primary user
- * can have managed profiles. Modify this code if that changes in the future.
- */
- void onProfilesChanged() {
- synchronized (this) {
- mManagedProfiles = mUserManager.getProfiles(UserHandle.USER_OWNER);
- if (mManagedProfiles != null) {
- // Remove the primary user from the list
- for (int i = mManagedProfiles.size() - 1; i >= 0; i--) {
- if (mManagedProfiles.get(i).id == UserHandle.USER_OWNER) {
- mManagedProfiles.remove(i);
- }
- }
- // If there are no managed profiles, reset the variable
- if (mManagedProfiles.size() == 0) {
- mManagedProfiles = null;
- }
- }
- if (LOCAL_LOGV) {
- Slog.d(TAG, "Managed Profiles = " + mManagedProfiles);
- }
- }
- }
-
- private void establishDbTracking(int userHandle) {
- if (LOCAL_LOGV) {
- Slog.i(TAG, "Installing settings db helper and caches for user " + userHandle);
- }
-
- DatabaseHelper dbhelper;
-
- synchronized (this) {
- dbhelper = mOpenHelpers.get(userHandle);
- if (dbhelper == null) {
- dbhelper = new DatabaseHelper(getContext(), userHandle);
- mOpenHelpers.append(userHandle, dbhelper);
-
- sSystemCaches.append(userHandle, new SettingsCache(TABLE_SYSTEM));
- sSecureCaches.append(userHandle, new SettingsCache(TABLE_SECURE));
- sKnownMutationsInFlight.append(userHandle, new AtomicInteger(0));
- }
- }
-
- // Initialization of the db *outside* the locks. It's possible that racing
- // threads might wind up here, the second having read the cache entries
- // written by the first, but that's benign: the SQLite helper implementation
- // manages concurrency itself, and it's important that we not run the db
- // initialization with any of our own locks held, so we're fine.
- SQLiteDatabase db = dbhelper.getWritableDatabase();
-
- // Watch for external modifications to the database files,
- // keeping our caches in sync. We synchronize the observer set
- // separately, and of course it has to run after the db file
- // itself was set up by the DatabaseHelper.
- synchronized (sObserverInstances) {
- if (sObserverInstances.get(userHandle) == null) {
- SettingsFileObserver observer = new SettingsFileObserver(userHandle, db.getPath());
- sObserverInstances.append(userHandle, observer);
- observer.startWatching();
- }
- }
-
- ensureAndroidIdIsSet(userHandle);
-
- startAsyncCachePopulation(userHandle);
- }
-
- class CachePrefetchThread extends Thread {
- private int mUserHandle;
-
- CachePrefetchThread(int userHandle) {
- super("populate-settings-caches");
- mUserHandle = userHandle;
- }
-
- @Override
- public void run() {
- fullyPopulateCaches(mUserHandle);
- }
- }
-
- private void startAsyncCachePopulation(int userHandle) {
- new CachePrefetchThread(userHandle).start();
- }
-
- private void fullyPopulateCaches(final int userHandle) {
- DatabaseHelper dbHelper;
- synchronized (this) {
- dbHelper = mOpenHelpers.get(userHandle);
- }
- if (dbHelper == null) {
- // User is gone.
- return;
- }
- // Only populate the globals cache once, for the owning user
- if (userHandle == UserHandle.USER_OWNER) {
- fullyPopulateCache(dbHelper, TABLE_GLOBAL, sGlobalCache);
- }
- fullyPopulateCache(dbHelper, TABLE_SECURE, sSecureCaches.get(userHandle));
- fullyPopulateCache(dbHelper, TABLE_SYSTEM, sSystemCaches.get(userHandle));
- }
-
- // Slurp all values (if sane in number & size) into cache.
- private void fullyPopulateCache(DatabaseHelper dbHelper, String table, SettingsCache cache) {
- SQLiteDatabase db = dbHelper.getReadableDatabase();
- Cursor c = db.query(
- table,
- new String[] { Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE },
- null, null, null, null, null,
- "" + (MAX_CACHE_ENTRIES + 1) /* limit */);
- try {
- synchronized (cache) {
- cache.evictAll();
- cache.setFullyMatchesDisk(true); // optimistic
- int rows = 0;
- while (c.moveToNext()) {
- rows++;
- String name = c.getString(0);
- String value = c.getString(1);
- cache.populate(name, value);
- }
- if (rows > MAX_CACHE_ENTRIES) {
- // Somewhat redundant, as removeEldestEntry() will
- // have already done this, but to be explicit:
- cache.setFullyMatchesDisk(false);
- Log.d(TAG, "row count exceeds max cache entries for table " + table);
- }
- if (LOCAL_LOGV) Log.d(TAG, "cache for settings table '" + table
- + "' rows=" + rows + "; fullycached=" + cache.fullyMatchesDisk());
- }
- } finally {
- c.close();
- }
- }
-
- private boolean ensureAndroidIdIsSet(int userHandle) {
- final Cursor c = queryForUser(Settings.Secure.CONTENT_URI,
- new String[] { Settings.NameValueTable.VALUE },
- Settings.NameValueTable.NAME + "=?",
- new String[] { Settings.Secure.ANDROID_ID }, null,
- userHandle);
- try {
- final String value = c.moveToNext() ? c.getString(0) : null;
- if (value == null) {
- // sanity-check the user before touching the db
- final UserInfo user = mUserManager.getUserInfo(userHandle);
- if (user == null) {
- // can happen due to races when deleting users; treat as benign
- return false;
+ @Override
+ public Bundle call(String method, String name, Bundle args) {
+ synchronized (mLock) {
+ final int requestingUserId = getRequestingUserId(args);
+ switch (method) {
+ case Settings.CALL_METHOD_GET_GLOBAL: {
+ Setting setting = getGlobalSettingLocked(name);
+ return packageValueForCallResult(setting);
}
- final SecureRandom random = new SecureRandom();
- final String newAndroidIdValue = Long.toHexString(random.nextLong());
- final ContentValues values = new ContentValues();
- values.put(Settings.NameValueTable.NAME, Settings.Secure.ANDROID_ID);
- values.put(Settings.NameValueTable.VALUE, newAndroidIdValue);
- final Uri uri = insertForUser(Settings.Secure.CONTENT_URI, values, userHandle);
- if (uri == null) {
- Slog.e(TAG, "Unable to generate new ANDROID_ID for user " + userHandle);
- return false;
+ case Settings.CALL_METHOD_GET_SECURE: {
+ Setting setting = getSecureSettingLocked(name, requestingUserId);
+ return packageValueForCallResult(setting);
}
- Slog.d(TAG, "Generated and saved new ANDROID_ID [" + newAndroidIdValue
- + "] for user " + userHandle);
- // Write a dropbox entry if it's a restricted profile
- if (user.isRestricted()) {
- DropBoxManager dbm = (DropBoxManager)
- getContext().getSystemService(Context.DROPBOX_SERVICE);
- if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
- dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
- + ",restricted_profile_ssaid,"
- + newAndroidIdValue + "\n");
- }
+
+ case Settings.CALL_METHOD_GET_SYSTEM: {
+ Setting setting = getSystemSettingLocked(name, requestingUserId);
+ return packageValueForCallResult(setting);
}
- }
- return true;
- } finally {
- c.close();
- }
- }
- // Lazy-initialize the settings caches for non-primary users
- private SettingsCache getOrConstructCache(int callingUser, SparseArray<SettingsCache> which) {
- getOrEstablishDatabase(callingUser); // ignore return value; we don't need it
- return which.get(callingUser);
- }
+ case Settings.CALL_METHOD_PUT_GLOBAL: {
+ String value = getSettingValue(args);
+ insertGlobalSettingLocked(name, value, requestingUserId);
+ } break;
- // Lazy initialize the database helper and caches for this user, if necessary
- private DatabaseHelper getOrEstablishDatabase(int callingUser) {
- if (callingUser >= Process.SYSTEM_UID) {
- if (USER_CHECK_THROWS) {
- throw new IllegalArgumentException("Uid rather than user handle: " + callingUser);
- } else {
- Slog.wtf(TAG, "establish db for uid rather than user: " + callingUser);
- }
- }
+ case Settings.CALL_METHOD_PUT_SECURE: {
+ String value = getSettingValue(args);
+ insertSecureSettingLocked(name, value, requestingUserId);
+ } break;
- long oldId = Binder.clearCallingIdentity();
- try {
- DatabaseHelper dbHelper;
- synchronized (this) {
- dbHelper = mOpenHelpers.get(callingUser);
- }
- if (null == dbHelper) {
- establishDbTracking(callingUser);
- synchronized (this) {
- dbHelper = mOpenHelpers.get(callingUser);
- }
- }
- return dbHelper;
- } finally {
- Binder.restoreCallingIdentity(oldId);
- }
- }
+ case Settings.CALL_METHOD_PUT_SYSTEM: {
+ String value = getSettingValue(args);
+ insertSystemSettingLocked(name, value, requestingUserId);
+ } break;
- public SettingsCache cacheForTable(final int callingUser, String tableName) {
- if (TABLE_SYSTEM.equals(tableName)) {
- return getOrConstructCache(callingUser, sSystemCaches);
- }
- if (TABLE_SECURE.equals(tableName)) {
- return getOrConstructCache(callingUser, sSecureCaches);
- }
- if (TABLE_GLOBAL.equals(tableName)) {
- return sGlobalCache;
+ default: {
+ Slog.w(LOG_TAG, "call() with invalid method: " + method);
+ } break;
+ }
}
return null;
}
- /**
- * Used for wiping a whole cache on deletes when we're not
- * sure what exactly was deleted or changed.
- */
- public void invalidateCache(final int callingUser, String tableName) {
- SettingsCache cache = cacheForTable(callingUser, tableName);
- if (cache == null) {
- return;
- }
- synchronized (cache) {
- cache.evictAll();
- cache.mCacheFullyMatchesDisk = false;
- }
- }
-
- /**
- * Checks if the calling user is a managed profile of the primary user.
- * Currently only the primary user (USER_OWNER) can have managed profiles.
- * @param callingUser the user trying to read/write settings
- * @return true if it is a managed profile of the primary user
- */
- private boolean isManagedProfile(int callingUser) {
- synchronized (this) {
- if (mManagedProfiles == null) return false;
- for (int i = mManagedProfiles.size() - 1; i >= 0; i--) {
- if (mManagedProfiles.get(i).id == callingUser) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * Fast path that avoids the use of chatty remoted Cursors.
- */
@Override
- public Bundle call(String method, String request, Bundle args) {
- int callingUser = UserHandle.getCallingUserId();
- if (args != null) {
- int reqUser = args.getInt(Settings.CALL_METHOD_USER_KEY, callingUser);
- if (reqUser != callingUser) {
- callingUser = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), reqUser, false, true,
- "get/set setting for user", null);
- if (LOCAL_LOGV) Slog.v(TAG, " access setting for user " + callingUser);
- }
- }
-
- // Note: we assume that get/put operations for moved-to-global names have already
- // been directed to the new location on the caller side (otherwise we'd fix them
- // up here).
- DatabaseHelper dbHelper;
- SettingsCache cache;
-
- // Get methods
- if (Settings.CALL_METHOD_GET_SYSTEM.equals(method)) {
- if (LOCAL_LOGV) Slog.v(TAG, "call(system:" + request + ") for " + callingUser);
- // Check if this request should be (re)directed to the primary user's db
- if (callingUser != UserHandle.USER_OWNER
- && shouldShadowParentProfile(callingUser, sSystemCloneToManagedKeys, request)) {
- callingUser = UserHandle.USER_OWNER;
- }
- dbHelper = getOrEstablishDatabase(callingUser);
- cache = sSystemCaches.get(callingUser);
- return lookupValue(dbHelper, TABLE_SYSTEM, cache, request);
- }
- if (Settings.CALL_METHOD_GET_SECURE.equals(method)) {
- if (LOCAL_LOGV) Slog.v(TAG, "call(secure:" + request + ") for " + callingUser);
- // Check if this is a setting to be copied from the primary user
- if (shouldShadowParentProfile(callingUser, sSecureCloneToManagedKeys, request)) {
- // If the request if for location providers and there's a restriction, return none
- if (Secure.LOCATION_PROVIDERS_ALLOWED.equals(request)
- && mUserManager.hasUserRestriction(
- UserManager.DISALLOW_SHARE_LOCATION, new UserHandle(callingUser))) {
- return sSecureCaches.get(callingUser).putIfAbsent(request, "");
- }
- callingUser = UserHandle.USER_OWNER;
- }
- dbHelper = getOrEstablishDatabase(callingUser);
- cache = sSecureCaches.get(callingUser);
- return lookupValue(dbHelper, TABLE_SECURE, cache, request);
- }
- if (Settings.CALL_METHOD_GET_GLOBAL.equals(method)) {
- if (LOCAL_LOGV) Slog.v(TAG, "call(global:" + request + ") for " + callingUser);
- // fast path: owner db & cache are immutable after onCreate() so we need not
- // guard on the attempt to look them up
- return lookupValue(getOrEstablishDatabase(UserHandle.USER_OWNER), TABLE_GLOBAL,
- sGlobalCache, request);
- }
-
- // Put methods - new value is in the args bundle under the key named by
- // the Settings.NameValueTable.VALUE static.
- final String newValue = (args == null)
- ? null : args.getString(Settings.NameValueTable.VALUE);
-
- // Framework can't do automatic permission checking for calls, so we need
- // to do it here.
- if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- String.format("Permission denial: writing to settings requires %1$s",
- android.Manifest.permission.WRITE_SETTINGS));
- }
-
- // Also need to take care of app op.
- if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SETTINGS, Binder.getCallingUid(),
- getCallingPackage()) != AppOpsManager.MODE_ALLOWED) {
- return null;
- }
-
- final ContentValues values = new ContentValues();
- values.put(Settings.NameValueTable.NAME, request);
- values.put(Settings.NameValueTable.VALUE, newValue);
- if (Settings.CALL_METHOD_PUT_SYSTEM.equals(method)) {
- if (LOCAL_LOGV) {
- Slog.v(TAG, "call_put(system:" + request + "=" + newValue + ") for "
- + callingUser);
- }
- // Extra check for USER_OWNER to optimize for the 99%
- if (callingUser != UserHandle.USER_OWNER && shouldShadowParentProfile(callingUser,
- sSystemCloneToManagedKeys, request)) {
- // Don't write these settings, as they are cloned from the parent profile
- return null;
- }
- insertForUser(Settings.System.CONTENT_URI, values, callingUser);
- // Clone the settings to the managed profiles so that notifications can be sent out
- if (callingUser == UserHandle.USER_OWNER && mManagedProfiles != null
- && sSystemCloneToManagedKeys.contains(request)) {
- final long token = Binder.clearCallingIdentity();
- try {
- for (int i = mManagedProfiles.size() - 1; i >= 0; i--) {
- if (LOCAL_LOGV) {
- Slog.v(TAG, "putting to additional user "
- + mManagedProfiles.get(i).id);
- }
- insertForUser(Settings.System.CONTENT_URI, values,
- mManagedProfiles.get(i).id);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- } else if (Settings.CALL_METHOD_PUT_SECURE.equals(method)) {
- if (LOCAL_LOGV) {
- Slog.v(TAG, "call_put(secure:" + request + "=" + newValue + ") for "
- + callingUser);
- }
- // Extra check for USER_OWNER to optimize for the 99%
- if (callingUser != UserHandle.USER_OWNER && shouldShadowParentProfile(callingUser,
- sSecureCloneToManagedKeys, request)) {
- // Don't write these settings, as they are cloned from the parent profile
- return null;
- }
- insertForUser(Settings.Secure.CONTENT_URI, values, callingUser);
- // Clone the settings to the managed profiles so that notifications can be sent out
- if (callingUser == UserHandle.USER_OWNER && mManagedProfiles != null
- && sSecureCloneToManagedKeys.contains(request)) {
- final long token = Binder.clearCallingIdentity();
- try {
- for (int i = mManagedProfiles.size() - 1; i >= 0; i--) {
- if (LOCAL_LOGV) {
- Slog.v(TAG, "putting to additional user "
- + mManagedProfiles.get(i).id);
- }
- try {
- insertForUser(Settings.Secure.CONTENT_URI, values,
- mManagedProfiles.get(i).id);
- } catch (SecurityException e) {
- // Temporary fix, see b/17450158
- Slog.w(TAG, "Cannot clone request '" + request + "' with value '"
- + newValue + "' to managed profile (id "
- + mManagedProfiles.get(i).id + ")", e);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- } else if (Settings.CALL_METHOD_PUT_GLOBAL.equals(method)) {
- if (LOCAL_LOGV) {
- Slog.v(TAG, "call_put(global:" + request + "=" + newValue + ") for "
- + callingUser);
- }
- insertForUser(Settings.Global.CONTENT_URI, values, callingUser);
- } else {
- Slog.w(TAG, "call() with invalid method: " + method);
- }
-
- return null;
- }
-
- /**
- * Check if the user is a managed profile and name is one of the settings to be cloned
- * from the parent profile.
- */
- private boolean shouldShadowParentProfile(int userId, HashSet<String> keys, String name) {
- return isManagedProfile(userId) && keys.contains(name);
- }
-
- // Looks up value 'key' in 'table' and returns either a single-pair Bundle,
- // possibly with a null value, or null on failure.
- private Bundle lookupValue(DatabaseHelper dbHelper, String table,
- final SettingsCache cache, String key) {
- if (cache == null) {
- Slog.e(TAG, "cache is null for user " + UserHandle.getCallingUserId() + " : key=" + key);
- return null;
- }
- synchronized (cache) {
- Bundle value = cache.get(key);
- if (value != null) {
- if (value != TOO_LARGE_TO_CACHE_MARKER) {
- return value;
- }
- // else we fall through and read the value from disk
- } else if (cache.fullyMatchesDisk()) {
- // Fast path (very common). Don't even try touch disk
- // if we know we've slurped it all in. Trying to
- // touch the disk would mean waiting for yaffs2 to
- // give us access, which could takes hundreds of
- // milliseconds. And we're very likely being called
- // from somebody's UI thread...
- return NULL_SETTING;
- }
- }
-
- SQLiteDatabase db = dbHelper.getReadableDatabase();
- Cursor cursor = null;
- try {
- cursor = db.query(table, COLUMN_VALUE, "name=?", new String[]{key},
- null, null, null, null);
- if (cursor != null && cursor.getCount() == 1) {
- cursor.moveToFirst();
- return cache.putIfAbsent(key, cursor.getString(0));
- }
- } catch (SQLiteException e) {
- Log.w(TAG, "settings lookup error", e);
- return null;
- } finally {
- if (cursor != null) cursor.close();
- }
- cache.putIfAbsent(key, null);
- return NULL_SETTING;
- }
-
- @Override
- public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) {
- return queryForUser(url, select, where, whereArgs, sort, UserHandle.getCallingUserId());
- }
-
- private Cursor queryForUser(Uri url, String[] select, String where, String[] whereArgs,
- String sort, int forUser) {
- if (LOCAL_LOGV) Slog.v(TAG, "query(" + url + ") for user " + forUser);
- SqlArguments args = new SqlArguments(url, where, whereArgs);
- DatabaseHelper dbH;
- dbH = getOrEstablishDatabase(
- TABLE_GLOBAL.equals(args.table) ? UserHandle.USER_OWNER : forUser);
- SQLiteDatabase db = dbH.getReadableDatabase();
-
- // The favorites table was moved from this provider to a provider inside Home
- // Home still need to query this table to upgrade from pre-cupcake builds
- // However, a cupcake+ build with no data does not contain this table which will
- // cause an exception in the SQL stack. The following line is a special case to
- // let the caller of the query have a chance to recover and avoid the exception
- if (TABLE_FAVORITES.equals(args.table)) {
- return null;
- } else if (TABLE_OLD_FAVORITES.equals(args.table)) {
- args.table = TABLE_FAVORITES;
- Cursor cursor = db.rawQuery("PRAGMA table_info(favorites);", null);
- if (cursor != null) {
- boolean exists = cursor.getCount() > 0;
- cursor.close();
- if (!exists) return null;
- } else {
- return null;
- }
- }
-
- SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
- qb.setTables(args.table);
-
- Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort);
- // the default Cursor interface does not support per-user observation
- try {
- AbstractCursor c = (AbstractCursor) ret;
- c.setNotificationUri(getContext().getContentResolver(), url, forUser);
- } catch (ClassCastException e) {
- // details of the concrete Cursor implementation have changed and this code has
- // not been updated to match -- complain and fail hard.
- Log.wtf(TAG, "Incompatible cursor derivation!");
- throw e;
- }
- return ret;
- }
-
- @Override
- public String getType(Uri url) {
- // If SqlArguments supplies a where clause, then it must be an item
- // (because we aren't supplying our own where clause).
- SqlArguments args = new SqlArguments(url, null, null);
- if (TextUtils.isEmpty(args.where)) {
+ public String getType(Uri uri) {
+ Arguments args = new Arguments(uri, null, null, true);
+ if (TextUtils.isEmpty(args.name)) {
return "vnd.android.cursor.dir/" + args.table;
} else {
- return "vnd.android.cursor.item/" + args.table;
+ return "vnd.android.cursor.item/" + args.table;
}
}
@Override
- public int bulkInsert(Uri uri, ContentValues[] values) {
- final int callingUser = UserHandle.getCallingUserId();
- if (LOCAL_LOGV) Slog.v(TAG, "bulkInsert() for user " + callingUser);
- SqlArguments args = new SqlArguments(uri);
- if (TABLE_FAVORITES.equals(args.table)) {
- return 0;
- }
- checkWritePermissions(args);
- SettingsCache cache = cacheForTable(callingUser, args.table);
-
- final AtomicInteger mutationCount;
- synchronized (this) {
- mutationCount = sKnownMutationsInFlight.get(callingUser);
- }
- if (mutationCount != null) {
- mutationCount.incrementAndGet();
- }
- DatabaseHelper dbH = getOrEstablishDatabase(
- TABLE_GLOBAL.equals(args.table) ? UserHandle.USER_OWNER : callingUser);
- SQLiteDatabase db = dbH.getWritableDatabase();
- db.beginTransaction();
- try {
- int numValues = values.length;
- for (int i = 0; i < numValues; i++) {
- checkUserRestrictions(values[i].getAsString(Settings.Secure.NAME), callingUser);
- if (db.insert(args.table, null, values[i]) < 0) return 0;
- SettingsCache.populate(cache, values[i]);
- if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + values[i]);
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- if (mutationCount != null) {
- mutationCount.decrementAndGet();
- }
+ public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs,
+ String order) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "query() for user: " + UserHandle.getCallingUserId());
}
- sendNotify(uri, callingUser);
- return values.length;
- }
+ Arguments args = new Arguments(uri, where, whereArgs, true);
+ String[] normalizedProjection = normalizeProjection(projection);
- /*
- * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
- * This setting contains a list of the currently enabled location providers.
- * But helper functions in android.providers.Settings can enable or disable
- * a single provider by using a "+" or "-" prefix before the provider name.
- *
- * @returns whether the database needs to be updated or not, also modifying
- * 'initialValues' if needed.
- */
- private boolean parseProviderList(Uri url, ContentValues initialValues, int desiredUser) {
- String value = initialValues.getAsString(Settings.Secure.VALUE);
- String newProviders = null;
- if (value != null && value.length() > 1) {
- char prefix = value.charAt(0);
- if (prefix == '+' || prefix == '-') {
- // skip prefix
- value = value.substring(1);
+ // If a legacy table that is gone, done.
+ if (REMOVED_LEGACY_TABLES.contains(args.table)) {
+ return new MatrixCursor(normalizedProjection, 0);
+ }
- // read list of enabled providers into "providers"
- String providers = "";
- String[] columns = {Settings.Secure.VALUE};
- String where = Settings.Secure.NAME + "=\'" + Settings.Secure.LOCATION_PROVIDERS_ALLOWED + "\'";
- Cursor cursor = queryForUser(url, columns, where, null, null, desiredUser);
- if (cursor != null && cursor.getCount() == 1) {
- try {
- cursor.moveToFirst();
- providers = cursor.getString(0);
- } finally {
- cursor.close();
- }
- }
-
- int index = providers.indexOf(value);
- int end = index + value.length();
- // check for commas to avoid matching on partial string
- if (index > 0 && providers.charAt(index - 1) != ',') index = -1;
- if (end < providers.length() && providers.charAt(end) != ',') index = -1;
-
- if (prefix == '+' && index < 0) {
- // append the provider to the list if not present
- if (providers.length() == 0) {
- newProviders = value;
+ synchronized (mLock) {
+ switch (args.table) {
+ case TABLE_GLOBAL: {
+ if (args.name != null) {
+ Setting setting = getGlobalSettingLocked(args.name);
+ return packageSettingForQuery(setting, normalizedProjection);
} else {
- newProviders = providers + ',' + value;
+ return getAllGlobalSettingsLocked(projection);
}
- } else if (prefix == '-' && index >= 0) {
- // remove the provider from the list if present
- // remove leading or trailing comma
- if (index > 0) {
- index--;
- } else if (end < providers.length()) {
- end++;
- }
-
- newProviders = providers.substring(0, index);
- if (end < providers.length()) {
- newProviders += providers.substring(end);
- }
- } else {
- // nothing changed, so no need to update the database
- return false;
}
- if (newProviders != null) {
- initialValues.put(Settings.Secure.VALUE, newProviders);
+ case TABLE_SECURE: {
+ final int userId = UserHandle.getCallingUserId();
+ if (args.name != null) {
+ Setting setting = getSecureSettingLocked(args.name, userId);
+ return packageSettingForQuery(setting, normalizedProjection);
+ } else {
+ return getAllSecureSettingsLocked(userId, projection);
+ }
+ }
+
+ case TABLE_SYSTEM: {
+ final int userId = UserHandle.getCallingUserId();
+ if (args.name != null) {
+ Setting setting = getSystemSettingLocked(args.name, userId);
+ return packageSettingForQuery(setting, normalizedProjection);
+ } else {
+ return getAllSystemSettingsLocked(userId, projection);
+ }
+ }
+
+ default: {
+ throw new IllegalArgumentException("Invalid Uri path:" + uri);
}
}
}
-
- return true;
}
@Override
- public Uri insert(Uri url, ContentValues initialValues) {
- return insertForUser(url, initialValues, UserHandle.getCallingUserId());
- }
-
- // Settings.put*ForUser() always winds up here, so this is where we apply
- // policy around permission to write settings for other users.
- private Uri insertForUser(Uri url, ContentValues initialValues, int desiredUserHandle) {
- final int callingUser = UserHandle.getCallingUserId();
- if (callingUser != desiredUserHandle) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "Not permitted to access settings for other users");
+ public Uri insert(Uri uri, ContentValues values) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "insert() for user: " + UserHandle.getCallingUserId());
}
- if (LOCAL_LOGV) Slog.v(TAG, "insert(" + url + ") for user " + desiredUserHandle
- + " by " + callingUser);
+ String table = getValidTableOrThrow(uri);
- SqlArguments args = new SqlArguments(url);
- if (TABLE_FAVORITES.equals(args.table)) {
+ // If a legacy table that is gone, done.
+ if (REMOVED_LEGACY_TABLES.contains(table)) {
return null;
}
- // Special case LOCATION_PROVIDERS_ALLOWED.
- // Support enabling/disabling a single provider (using "+" or "-" prefix)
- String name = initialValues.getAsString(Settings.Secure.NAME);
- if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
- if (!parseProviderList(url, initialValues, desiredUserHandle)) return null;
+ String name = values.getAsString(Settings.Secure.NAME);
+ if (TextUtils.isEmpty(name)) {
+ return null;
}
- // If this is an insert() of a key that has been migrated to the global store,
- // redirect the operation to that store
- if (name != null) {
- if (sSecureGlobalKeys.contains(name) || sSystemGlobalKeys.contains(name)) {
- if (!TABLE_GLOBAL.equals(args.table)) {
- if (LOCAL_LOGV) Slog.i(TAG, "Rewrite of insert() of now-global key " + name);
+ String value = values.getAsString(Settings.Secure.VALUE);
+
+ synchronized (mLock) {
+ switch (table) {
+ case TABLE_GLOBAL: {
+ if (insertGlobalSettingLocked(name, value, UserHandle.getCallingUserId())) {
+ return Uri.withAppendedPath(Settings.Global.CONTENT_URI, name);
+ }
+ } break;
+
+ case TABLE_SECURE: {
+ if (insertSecureSettingLocked(name, value, UserHandle.getCallingUserId())) {
+ return Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
+ }
+ } break;
+
+ case TABLE_SYSTEM: {
+ if (insertSystemSettingLocked(name, value, UserHandle.getCallingUserId())) {
+ return Uri.withAppendedPath(Settings.System.CONTENT_URI, name);
+ }
+ } break;
+
+ default: {
+ throw new IllegalArgumentException("Bad Uri path:" + uri);
}
- args.table = TABLE_GLOBAL; // next condition will rewrite the user handle
}
}
- // Check write permissions only after determining which table the insert will touch
- checkWritePermissions(args);
-
- checkUserRestrictions(name, desiredUserHandle);
-
- // The global table is stored under the owner, always
- if (TABLE_GLOBAL.equals(args.table)) {
- desiredUserHandle = UserHandle.USER_OWNER;
- }
-
- SettingsCache cache = cacheForTable(desiredUserHandle, args.table);
- String value = initialValues.getAsString(Settings.NameValueTable.VALUE);
- if (SettingsCache.isRedundantSetValue(cache, name, value)) {
- return Uri.withAppendedPath(url, name);
- }
-
- final AtomicInteger mutationCount;
- synchronized (this) {
- mutationCount = sKnownMutationsInFlight.get(callingUser);
- }
- if (mutationCount != null) {
- mutationCount.incrementAndGet();
- }
- DatabaseHelper dbH = getOrEstablishDatabase(desiredUserHandle);
- SQLiteDatabase db = dbH.getWritableDatabase();
- final long rowId = db.insert(args.table, null, initialValues);
- if (mutationCount != null) {
- mutationCount.decrementAndGet();
- }
- if (rowId <= 0) return null;
-
- SettingsCache.populate(cache, initialValues); // before we notify
-
- if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues
- + " for user " + desiredUserHandle);
- // Note that we use the original url here, not the potentially-rewritten table name
- url = getUriFor(url, initialValues, rowId);
- sendNotify(url, desiredUserHandle);
- return url;
+ return null;
}
@Override
- public int delete(Uri url, String where, String[] whereArgs) {
- int callingUser = UserHandle.getCallingUserId();
- if (LOCAL_LOGV) Slog.v(TAG, "delete() for user " + callingUser);
- SqlArguments args = new SqlArguments(url, where, whereArgs);
- if (TABLE_FAVORITES.equals(args.table)) {
- return 0;
- } else if (TABLE_OLD_FAVORITES.equals(args.table)) {
- args.table = TABLE_FAVORITES;
- } else if (TABLE_GLOBAL.equals(args.table)) {
- callingUser = UserHandle.USER_OWNER;
+ public int bulkInsert(Uri uri, ContentValues[] allValues) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "bulkInsert() for user: " + UserHandle.getCallingUserId());
}
- checkWritePermissions(args);
- final AtomicInteger mutationCount;
- synchronized (this) {
- mutationCount = sKnownMutationsInFlight.get(callingUser);
+ int insertionCount = 0;
+ final int valuesCount = allValues.length;
+ for (int i = 0; i < valuesCount; i++) {
+ ContentValues values = allValues[i];
+ if (insert(uri, values) != null) {
+ insertionCount++;
+ }
}
- if (mutationCount != null) {
- mutationCount.incrementAndGet();
- }
- DatabaseHelper dbH = getOrEstablishDatabase(callingUser);
- SQLiteDatabase db = dbH.getWritableDatabase();
- int count = db.delete(args.table, args.where, args.args);
- if (mutationCount != null) {
- mutationCount.decrementAndGet();
- }
- if (count > 0) {
- invalidateCache(callingUser, args.table); // before we notify
- sendNotify(url, callingUser);
- }
- startAsyncCachePopulation(callingUser);
- if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted");
- return count;
+
+ return insertionCount;
}
@Override
- public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) {
- // NOTE: update() is never called by the front-end Settings API, and updates that
- // wind up affecting rows in Secure that are globally shared will not have the
- // intended effect (the update will be invisible to the rest of the system).
- // This should have no practical effect, since writes to the Secure db can only
- // be done by system code, and that code should be using the correct API up front.
- int callingUser = UserHandle.getCallingUserId();
- if (LOCAL_LOGV) Slog.v(TAG, "update() for user " + callingUser);
- SqlArguments args = new SqlArguments(url, where, whereArgs);
- if (TABLE_FAVORITES.equals(args.table)) {
- return 0;
- } else if (TABLE_GLOBAL.equals(args.table)) {
- callingUser = UserHandle.USER_OWNER;
+ public int delete(Uri uri, String where, String[] whereArgs) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "delete() for user: " + UserHandle.getCallingUserId());
}
- checkWritePermissions(args);
- checkUserRestrictions(initialValues.getAsString(Settings.Secure.NAME), callingUser);
- final AtomicInteger mutationCount;
- synchronized (this) {
- mutationCount = sKnownMutationsInFlight.get(callingUser);
+ Arguments args = new Arguments(uri, where, whereArgs, false);
+
+ // If a legacy table that is gone, done.
+ if (REMOVED_LEGACY_TABLES.contains(args.table)) {
+ return 0;
}
- if (mutationCount != null) {
- mutationCount.incrementAndGet();
+
+ if (TextUtils.isEmpty(args.name)) {
+ return 0;
}
- DatabaseHelper dbH = getOrEstablishDatabase(callingUser);
- SQLiteDatabase db = dbH.getWritableDatabase();
- int count = db.update(args.table, initialValues, args.where, args.args);
- if (mutationCount != null) {
- mutationCount.decrementAndGet();
+
+ synchronized (mLock) {
+ switch (args.table) {
+ case TABLE_GLOBAL: {
+ final int userId = UserHandle.getCallingUserId();
+ return deleteGlobalSettingLocked(args.name, userId) ? 1 : 0;
+ }
+
+ case TABLE_SECURE: {
+ final int userId = UserHandle.getCallingUserId();
+ return deleteSecureSettingLocked(args.name, userId) ? 1 : 0;
+ }
+
+ case TABLE_SYSTEM: {
+ final int userId = UserHandle.getCallingUserId();
+ return deleteSystemSettingLocked(args.name, userId) ? 1 : 0;
+ }
+
+ default: {
+ throw new IllegalArgumentException("Bad Uri path:" + uri);
+ }
+ }
}
- if (count > 0) {
- invalidateCache(callingUser, args.table); // before we notify
- sendNotify(url, callingUser);
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "update() for user: " + UserHandle.getCallingUserId());
}
- startAsyncCachePopulation(callingUser);
- if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues);
- return count;
+
+ Arguments args = new Arguments(uri, where, whereArgs, false);
+
+ // If a legacy table that is gone, done.
+ if (REMOVED_LEGACY_TABLES.contains(args.table)) {
+ return 0;
+ }
+
+ String value = values.getAsString(Settings.Secure.VALUE);
+ if (TextUtils.isEmpty(value)) {
+ return 0;
+ }
+
+ synchronized (mLock) {
+ switch (args.table) {
+ case TABLE_GLOBAL: {
+ final int userId = UserHandle.getCallingUserId();
+ return updateGlobalSettingLocked(args.name, value, userId) ? 1 : 0;
+ }
+
+ case TABLE_SECURE: {
+ final int userId = UserHandle.getCallingUserId();
+ return updateSecureSettingLocked(args.name, value, userId) ? 1 : 0;
+ }
+
+ case TABLE_SYSTEM: {
+ final int userId = UserHandle.getCallingUserId();
+ return updateSystemSettingLocked(args.name, value, userId) ? 1 : 0;
+ }
+
+ default: {
+ throw new IllegalArgumentException("Invalid Uri path:" + uri);
+ }
+ }
+ }
}
@Override
@@ -1229,102 +481,1418 @@
+ "ringtone playback is available through android.media.Ringtone");
}
- /**
- * In-memory LRU Cache of system and secure settings, along with
- * associated helper functions to keep cache coherent with the
- * database.
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mLock) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ List<UserInfo> users = mUserManager.getUsers(true);
+ final int userCount = users.size();
+ for (int i = 0; i < userCount; i++) {
+ UserInfo user = users.get(i);
+ dumpForUser(user.id, pw);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private void dumpForUser(int userId, PrintWriter pw) {
+ if (userId == UserHandle.USER_OWNER) {
+ pw.println("GLOBAL SETTINGS (user " + userId + ")");
+ Cursor globalCursor = getAllGlobalSettingsLocked(ALL_COLUMNS);
+ dumpSettings(globalCursor, pw);
+ pw.println();
+ }
+
+ pw.println("SECURE SETTINGS (user " + userId + ")");
+ Cursor secureCursor = getAllSecureSettingsLocked(userId, ALL_COLUMNS);
+ dumpSettings(secureCursor, pw);
+ pw.println();
+
+ pw.println("SYSTEM SETTINGS (user " + userId + ")");
+ Cursor systemCursor = getAllSystemSettingsLocked(userId, ALL_COLUMNS);
+ dumpSettings(systemCursor, pw);
+ pw.println();
+ }
+
+ private void dumpSettings(Cursor cursor, PrintWriter pw) {
+ if (!cursor.moveToFirst()) {
+ return;
+ }
+
+ final int idColumnIdx = cursor.getColumnIndex(Settings.NameValueTable._ID);
+ final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
+ final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+
+ do {
+ pw.append("_id:").append(cursor.getString(idColumnIdx));
+ pw.append(" name:").append(cursor.getString(nameColumnIdx));
+ pw.append(" value:").append(cursor.getString(valueColumnIdx));
+ pw.println();
+ } while (cursor.moveToNext());
+ }
+
+ private void registerBroadcastReceivers() {
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_STOPPED);
+
+ getContext().registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_OWNER);
+
+ switch (intent.getAction()) {
+ case Intent.ACTION_USER_REMOVED: {
+ mSettingsRegistry.removeUserStateLocked(userId, true);
+ } break;
+
+ case Intent.ACTION_USER_STOPPED: {
+ mSettingsRegistry.removeUserStateLocked(userId, false);
+ } break;
+ }
+ }
+ }, userFilter);
+
+ PackageMonitor monitor = new PackageMonitor() {
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ synchronized (mLock) {
+ mSettingsRegistry.onPackageRemovedLocked(packageName,
+ UserHandle.getUserId(uid));
+ }
+ }
+ };
+
+ // package changes
+ monitor.register(getContext(), BackgroundThread.getHandler().getLooper(),
+ UserHandle.ALL, true);
+ }
+
+ private Cursor getAllGlobalSettingsLocked(String[] projection) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getAllGlobalSettingsLocked()");
+ }
+
+ // Get the settings.
+ SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
+ SettingsRegistry.SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+
+ List<String> names = settingsState.getSettingNamesLocked();
+
+ final int nameCount = names.size();
+
+ String[] normalizedProjection = normalizeProjection(projection);
+ MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
+
+ // Anyone can get the global settings, so no security checks.
+ for (int i = 0; i < nameCount; i++) {
+ String name = names.get(i);
+ Setting setting = settingsState.getSettingLocked(name);
+ appendSettingToCursor(result, setting);
+ }
+
+ return result;
+ }
+
+ private Setting getGlobalSettingLocked(String name) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
+ }
+
+ // Get the value.
+ return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_OWNER, name);
+ }
+
+ private boolean updateGlobalSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "updateGlobalSettingLocked(" + name + ", " + value + ")");
+ }
+ return mutateGlobalSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
+ }
+
+ private boolean insertGlobalSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "insertGlobalSettingLocked(" + name + ", " + value + ")");
+ }
+ return mutateGlobalSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
+ }
+
+ private boolean deleteGlobalSettingLocked(String name, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "deleteGlobalSettingLocked(" + name + ")");
+ }
+ return mutateGlobalSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
+ }
+
+ private boolean mutateGlobalSettingLocked(String name, String value, int requestingUserId,
+ int operation) {
+ // Make sure the caller can change the settings - treated as secure.
+ enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
+
+ // Verify whether this operation is allowed for the calling package.
+ if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
+ return false;
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+
+ // If this is a setting that is currently restricted for this user, done.
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId)) {
+ return false;
+ }
+
+ // Perform the mutation.
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT: {
+ return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_OWNER, name, value, getCallingPackage());
+ }
+
+ case MUTATION_OPERATION_DELETE: {
+ return mSettingsRegistry.deleteSettingLocked(
+ SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_OWNER, name);
+ }
+
+ case MUTATION_OPERATION_UPDATE: {
+ return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_GLOBAL,
+ UserHandle.USER_OWNER, name, value, getCallingPackage());
+ }
+ }
+
+ return false;
+ }
+
+ private Cursor getAllSecureSettingsLocked(int userId, String[] projection) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getAllSecureSettings(" + userId + ")");
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+ List<String> names = mSettingsRegistry.getSettingsNamesLocked(
+ SettingsRegistry.SETTINGS_TYPE_SECURE, callingUserId);
+
+ final int nameCount = names.size();
+
+ String[] normalizedProjection = normalizeProjection(projection);
+ MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
+
+ for (int i = 0; i < nameCount; i++) {
+ String name = names.get(i);
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
+
+ // Special case for location (sigh).
+ if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
+ return null;
+ }
+
+ Setting setting = mSettingsRegistry.getSettingLocked(
+ SettingsRegistry.SETTINGS_TYPE_SECURE, owningUserId, name);
+ appendSettingToCursor(result, setting);
+ }
+
+ return result;
+ }
+
+ private Setting getSecureSettingLocked(String name, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
+
+ // Special case for location (sigh).
+ if (isLocationProvidersAllowedRestricted(name, callingUserId, owningUserId)) {
+ return null;
+ }
+
+ // Get the value.
+ return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, name);
+ }
+
+ private boolean insertSecureSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "insertSecureSettingLocked(" + name + ", " + value + ", "
+ + requestingUserId + ")");
+ }
+
+ return mutateSecureSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
+ }
+
+ private boolean deleteSecureSettingLocked(String name, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "deleteSecureSettingLocked(" + name + ", " + requestingUserId + ")");
+ }
+
+ return mutateSecureSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
+ }
+
+ private boolean updateSecureSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "updateSecureSettingLocked(" + name + ", " + value + ", "
+ + requestingUserId + ")");
+ }
+
+ return mutateSecureSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
+ }
+
+ private boolean mutateSecureSettingLocked(String name, String value, int requestingUserId,
+ int operation) {
+ // Make sure the caller can change the settings.
+ enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
+
+ // Verify whether this operation is allowed for the calling package.
+ if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
+ return false;
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+
+ // If this is a setting that is currently restricted for this user, done.
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId)) {
+ return false;
+ }
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
+
+ // Only the owning user can change the setting.
+ if (owningUserId != callingUserId) {
+ return false;
+ }
+
+ // Special cases for location providers (sigh).
+ if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
+ return updateLocationProvidersAllowedLocked(value, owningUserId);
+ }
+
+ // Mutate the value.
+ switch(operation) {
+ case MUTATION_OPERATION_INSERT: {
+ return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, name, value, getCallingPackage());
+ }
+
+ case MUTATION_OPERATION_DELETE: {
+ return mSettingsRegistry.deleteSettingLocked(
+ SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, name);
+ }
+
+ case MUTATION_OPERATION_UPDATE: {
+ return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, name, value, getCallingPackage());
+ }
+ }
+
+ return false;
+ }
+
+ private Cursor getAllSystemSettingsLocked(int userId, String[] projection) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getAllSecureSystemLocked(" + userId + ")");
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+ List<String> names = mSettingsRegistry.getSettingsNamesLocked(
+ SettingsRegistry.SETTINGS_TYPE_SYSTEM, callingUserId);
+
+ final int nameCount = names.size();
+
+ String[] normalizedProjection = normalizeProjection(projection);
+ MatrixCursor result = new MatrixCursor(normalizedProjection, nameCount);
+
+ for (int i = 0; i < nameCount; i++) {
+ String name = names.get(i);
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
+
+ Setting setting = mSettingsRegistry.getSettingLocked(
+ SettingsRegistry.SETTINGS_TYPE_SYSTEM, owningUserId, name);
+ appendSettingToCursor(result, setting);
+ }
+
+ return result;
+ }
+
+ private Setting getSystemSettingLocked(String name, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "getSystemSetting(" + name + ", " + requestingUserId + ")");
+ }
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
+
+ // Get the value.
+ return mSettingsRegistry.getSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
+ owningUserId, name);
+ }
+
+ private boolean insertSystemSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "insertSystemSettingLocked(" + name + ", " + value + ", "
+ + requestingUserId + ")");
+ }
+
+ return mutateSystemSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_INSERT);
+ }
+
+ private boolean deleteSystemSettingLocked(String name, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "deleteSystemSettingLocked(" + name + ", " + requestingUserId + ")");
+ }
+
+ return mutateSystemSettingLocked(name, null, requestingUserId, MUTATION_OPERATION_DELETE);
+ }
+
+ private boolean updateSystemSettingLocked(String name, String value, int requestingUserId) {
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "updateSystemSettingLocked(" + name + ", " + value + ", "
+ + requestingUserId + ")");
+ }
+
+ return mutateSystemSettingLocked(name, value, requestingUserId, MUTATION_OPERATION_UPDATE);
+ }
+
+ private boolean mutateSystemSettingLocked(String name, String value, int runAsUserId,
+ int operation) {
+ // Make sure the caller can change the settings.
+ enforceWritePermission(Manifest.permission.WRITE_SETTINGS);
+
+ // Verify whether this operation is allowed for the calling package.
+ if (!isAppOpWriteSettingsAllowedForCallingPackage()) {
+ return false;
+ }
+
+ // Enforce what the calling package can mutate in the system settings.
+ enforceRestrictedSystemSettingsMutationForCallingPackageLocked(operation, name);
+
+ // Resolve the userId on whose behalf the call is made.
+ final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(runAsUserId);
+
+ // Determine the owning user as some profile settings are cloned from the parent.
+ final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
+
+ // Only the owning user id can change the setting.
+ if (owningUserId != callingUserId) {
+ return false;
+ }
+
+ // Mutate the value.
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT: {
+ validateSystemSettingValue(name, value);
+ return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
+ owningUserId, name, value, getCallingPackage());
+ }
+
+ case MUTATION_OPERATION_DELETE: {
+ return mSettingsRegistry.deleteSettingLocked(
+ SettingsRegistry.SETTINGS_TYPE_SYSTEM,
+ owningUserId, name);
+ }
+
+ case MUTATION_OPERATION_UPDATE: {
+ validateSystemSettingValue(name, value);
+ return mSettingsRegistry.updateSettingLocked(SettingsRegistry.SETTINGS_TYPE_SYSTEM,
+ owningUserId, name, value, getCallingPackage());
+ }
+ }
+
+ return false;
+ }
+
+ private void validateSystemSettingValue(String name, String value) {
+ Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
+ if (validator != null && !validator.validate(value)) {
+ throw new IllegalArgumentException("Invalid value: " + value
+ + " for setting: " + name);
+ }
+ }
+
+ private boolean isLocationProvidersAllowedRestricted(String name, int callingUserId,
+ int owningUserId) {
+ // Optimization - location providers are restricted only for managed profiles.
+ if (callingUserId == owningUserId) {
+ return false;
+ }
+ if (Settings.Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)
+ && mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
+ new UserHandle(callingUserId))) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId) {
+ String restriction = sSettingToUserRestrictionMap.get(setting);
+ if (restriction == null) {
+ return false;
+ }
+ return mUserManager.hasUserRestriction(restriction, new UserHandle(userId));
+ }
+
+ private int resolveOwningUserIdForSecureSettingLocked(int userId, String setting) {
+ return resolveOwningUserIdLocked(userId, sSecureCloneToManagedSettings, setting);
+ }
+
+ private int resolveOwningUserIdForSystemSettingLocked(int userId, String setting) {
+ return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting);
+ }
+
+ private int resolveOwningUserIdLocked(int userId, Set<String> keys, String name) {
+ final int parentId = getGroupParentLocked(userId);
+ if (parentId != userId && keys.contains(name)) {
+ return parentId;
+ }
+ return userId;
+ }
+
+ private void enforceRestrictedSystemSettingsMutationForCallingPackageLocked(int operation,
+ String name) {
+ // System/root/shell can mutate whatever secure settings they want.
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == android.os.Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID
+ || callingUid == Process.ROOT_UID) {
+ return;
+ }
+
+ switch (operation) {
+ case MUTATION_OPERATION_INSERT:
+ // Insert updates.
+ case MUTATION_OPERATION_UPDATE: {
+ if (Settings.System.PUBLIC_SETTINGS.contains(name)) {
+ return;
+ }
+
+ // The calling package is already verified.
+ PackageInfo packageInfo = getCallingPackageInfoOrThrow();
+
+ // Privileged apps can do whatever they want.
+ if ((packageInfo.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
+ return;
+ }
+
+ warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
+ packageInfo.applicationInfo.targetSdkVersion, name);
+ } break;
+
+ case MUTATION_OPERATION_DELETE: {
+ if (Settings.System.PUBLIC_SETTINGS.contains(name)
+ || Settings.System.PRIVATE_SETTINGS.contains(name)) {
+ throw new IllegalArgumentException("You cannot delete system defined"
+ + " secure settings.");
+ }
+
+ // The calling package is already verified.
+ PackageInfo packageInfo = getCallingPackageInfoOrThrow();
+
+ // Privileged apps can do whatever they want.
+ if ((packageInfo.applicationInfo.privateFlags &
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
+ return;
+ }
+
+ warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
+ packageInfo.applicationInfo.targetSdkVersion, name);
+ } break;
+ }
+ }
+
+ private PackageInfo getCallingPackageInfoOrThrow() {
+ try {
+ return mPackageManager.getPackageInfo(getCallingPackage(), 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalStateException("Calling package doesn't exist");
+ }
+ }
+
+ private int getGroupParentLocked(int userId) {
+ // Most frequent use case.
+ if (userId == UserHandle.USER_OWNER) {
+ return userId;
+ }
+ // We are in the same process with the user manager and the returned
+ // user info is a cached instance, so just look up instead of cache.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ UserInfo userInfo = mUserManager.getProfileParent(userId);
+ return (userInfo != null) ? userInfo.id : userId;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean isAppOpWriteSettingsAllowedForCallingPackage() {
+ final int callingUid = Binder.getCallingUid();
+
+ mAppOpsManager.checkPackage(Binder.getCallingUid(), getCallingPackage());
+
+ return mAppOpsManager.noteOp(AppOpsManager.OP_WRITE_SETTINGS, callingUid,
+ getCallingPackage()) == AppOpsManager.MODE_ALLOWED;
+ }
+
+ private void enforceWritePermission(String permission) {
+ if (getContext().checkCallingOrSelfPermission(permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Permission denial: writing to settings requires:"
+ + permission);
+ }
+ }
+
+ /*
+ * Used to parse changes to the value of Settings.Secure.LOCATION_PROVIDERS_ALLOWED.
+ * This setting contains a list of the currently enabled location providers.
+ * But helper functions in android.providers.Settings can enable or disable
+ * a single provider by using a "+" or "-" prefix before the provider name.
+ *
+ * @returns whether the enabled location providers changed.
*/
- private static final class SettingsCache extends LruCache<String, Bundle> {
-
- private final String mCacheName;
- private boolean mCacheFullyMatchesDisk = false; // has the whole database slurped.
-
- public SettingsCache(String name) {
- super(MAX_CACHE_ENTRIES);
- mCacheName = name;
+ private boolean updateLocationProvidersAllowedLocked(String value, int owningUserId) {
+ if (TextUtils.isEmpty(value)) {
+ return false;
}
- /**
- * Is the whole database table slurped into this cache?
- */
- public boolean fullyMatchesDisk() {
- synchronized (this) {
- return mCacheFullyMatchesDisk;
+ final char prefix = value.charAt(0);
+ if (prefix != '+' && prefix != '-') {
+ return false;
+ }
+
+ // skip prefix
+ value = value.substring(1);
+
+ Setting settingValue = getSecureSettingLocked(
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+
+ String oldProviders = (settingValue != null) ? settingValue.getValue() : "";
+
+ int index = oldProviders.indexOf(value);
+ int end = index + value.length();
+
+ // check for commas to avoid matching on partial string
+ if (index > 0 && oldProviders.charAt(index - 1) != ',') {
+ index = -1;
+ }
+
+ // check for commas to avoid matching on partial string
+ if (end < oldProviders.length() && oldProviders.charAt(end) != ',') {
+ index = -1;
+ }
+
+ String newProviders;
+
+ if (prefix == '+' && index < 0) {
+ // append the provider to the list if not present
+ if (oldProviders.length() == 0) {
+ newProviders = value;
+ } else {
+ newProviders = oldProviders + ',' + value;
+ }
+ } else if (prefix == '-' && index >= 0) {
+ // remove the provider from the list if present
+ // remove leading or trailing comma
+ if (index > 0) {
+ index--;
+ } else if (end < oldProviders.length()) {
+ end++;
+ }
+
+ newProviders = oldProviders.substring(0, index);
+ if (end < oldProviders.length()) {
+ newProviders += oldProviders.substring(end);
+ }
+ } else {
+ // nothing changed, so no need to update the database
+ return false;
+ }
+
+ return mSettingsRegistry.insertSettingLocked(SettingsRegistry.SETTINGS_TYPE_SECURE,
+ owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
+ getCallingPackage());
+ }
+
+ private void sendNotify(Uri uri, int userId) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ getContext().getContentResolver().notifyChange(uri, null, true, userId);
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "Notifying for " + userId + ": " + uri);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
+ int targetSdkVersion, String name) {
+ // If the app targets Lollipop MR1 or older SDK we warn, otherwise crash.
+ if (targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
+ Slog.w(LOG_TAG, "You shouldn't not change private system settings."
+ + " This will soon become an error.");
+ } else {
+ Slog.w(LOG_TAG, "You shouldn't keep your settings in the secure settings."
+ + " This will soon become an error.");
+ }
+ } else {
+ if (Settings.System.PRIVATE_SETTINGS.contains(name)) {
+ throw new IllegalArgumentException("You cannot change private secure settings.");
+ } else {
+ throw new IllegalArgumentException("You cannot keep your settings in"
+ + " the secure settings.");
+ }
+ }
+ }
+
+ private static int resolveCallingUserIdEnforcingPermissionsLocked(int requestingUserId) {
+ if (requestingUserId == UserHandle.getCallingUserId()) {
+ return requestingUserId;
+ }
+ return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), requestingUserId, false, true,
+ "get/set setting for user", null);
+ }
+
+ private static Bundle packageValueForCallResult(Setting setting) {
+ if (setting == null) {
+ return NULL_SETTING;
+ }
+ return Bundle.forPair(Settings.NameValueTable.VALUE, setting.getValue());
+ }
+
+ private static int getRequestingUserId(Bundle args) {
+ final int callingUserId = UserHandle.getCallingUserId();
+ return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
+ : callingUserId;
+ }
+
+ private static String getSettingValue(Bundle args) {
+ return (args != null) ? args.getString(Settings.NameValueTable.VALUE) : null;
+ }
+
+ private static String getValidTableOrThrow(Uri uri) {
+ if (uri.getPathSegments().size() > 0) {
+ String table = uri.getPathSegments().get(0);
+ if (DatabaseHelper.isValidTable(table)) {
+ return table;
+ }
+ throw new IllegalArgumentException("Bad root path: " + table);
+ }
+ throw new IllegalArgumentException("Invalid URI:" + uri);
+ }
+
+ private static MatrixCursor packageSettingForQuery(Setting setting, String[] projection) {
+ if (setting == null) {
+ return new MatrixCursor(projection, 0);
+ }
+ MatrixCursor cursor = new MatrixCursor(projection, 1);
+ appendSettingToCursor(cursor, setting);
+ return cursor;
+ }
+
+ private static String[] normalizeProjection(String[] projection) {
+ if (projection == null) {
+ return ALL_COLUMNS;
+ }
+
+ final int columnCount = projection.length;
+ for (int i = 0; i < columnCount; i++) {
+ String column = projection[i];
+ if (!ArrayUtils.contains(ALL_COLUMNS, column)) {
+ throw new IllegalArgumentException("Invalid column: " + column);
}
}
- public void setFullyMatchesDisk(boolean value) {
- synchronized (this) {
- mCacheFullyMatchesDisk = value;
+ return projection;
+ }
+
+ private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
+ final int columnCount = cursor.getColumnCount();
+
+ String[] values = new String[columnCount];
+
+ for (int i = 0; i < columnCount; i++) {
+ String column = cursor.getColumnName(i);
+
+ switch (column) {
+ case Settings.NameValueTable._ID: {
+ values[i] = setting.getId();
+ } break;
+
+ case Settings.NameValueTable.NAME: {
+ values[i] = setting.getName();
+ } break;
+
+ case Settings.NameValueTable.VALUE: {
+ values[i] = setting.getValue();
+ } break;
}
}
- @Override
- protected void entryRemoved(boolean evicted, String key, Bundle oldValue, Bundle newValue) {
- if (evicted) {
- mCacheFullyMatchesDisk = false;
- }
- }
+ cursor.addRow(values);
+ }
- /**
- * Atomic cache population, conditional on size of value and if
- * we lost a race.
- *
- * @returns a Bundle to send back to the client from call(), even
- * if we lost the race.
- */
- public Bundle putIfAbsent(String key, String value) {
- Bundle bundle = (value == null) ? NULL_SETTING : Bundle.forPair("value", value);
- if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) {
- synchronized (this) {
- if (get(key) == null) {
- put(key, bundle);
+ private static final class Arguments {
+ private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS =
+ Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*");
+
+ private static final Pattern WHERE_PATTERN_WITH_PARAM_IN_BRACKETS =
+ Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*\\?[\\s]*\\)[\\s]*");
+
+ private static final Pattern WHERE_PATTERN_NO_PARAM_IN_BRACKETS =
+ Pattern.compile("[\\s]*\\([\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*\\)[\\s]*");
+
+ private static final Pattern WHERE_PATTERN_NO_PARAM_NO_BRACKETS =
+ Pattern.compile("[\\s]*name[\\s]*=[\\s]*['\"].*['\"][\\s]*");
+
+ public final String table;
+ public final String name;
+
+ public Arguments(Uri uri, String where, String[] whereArgs, boolean supportAll) {
+ final int segmentSize = uri.getPathSegments().size();
+ switch (segmentSize) {
+ case 1: {
+ if (where != null
+ && (WHERE_PATTERN_WITH_PARAM_NO_BRACKETS.matcher(where).matches()
+ || WHERE_PATTERN_WITH_PARAM_IN_BRACKETS.matcher(where).matches())
+ && whereArgs.length == 1) {
+ name = whereArgs[0];
+ table = computeTableForSetting(uri, name);
+ return;
+ } else if (where != null
+ && (WHERE_PATTERN_NO_PARAM_NO_BRACKETS.matcher(where).matches()
+ || WHERE_PATTERN_NO_PARAM_IN_BRACKETS.matcher(where).matches())) {
+ final int startIndex = Math.max(where.indexOf("'"),
+ where.indexOf("\"")) + 1;
+ final int endIndex = Math.max(where.lastIndexOf("'"),
+ where.lastIndexOf("\""));
+ name = where.substring(startIndex, endIndex);
+ table = computeTableForSetting(uri, name);
+ return;
+ } else if (supportAll && where == null && whereArgs == null) {
+ name = null;
+ table = computeTableForSetting(uri, null);
+ return;
}
+ } break;
+
+ case 2: {
+ if (where == null && whereArgs == null) {
+ name = uri.getPathSegments().get(1);
+ table = computeTableForSetting(uri, name);
+ return;
+ }
+ } break;
+ }
+
+ EventLogTags.writeUnsupportedSettingsQuery(
+ uri.toSafeString(), where, Arrays.toString(whereArgs));
+ String message = String.format( "Supported SQL:\n"
+ + " uri content://some_table/some_property with null where and where args\n"
+ + " uri content://some_table with query name=? and single name as arg\n"
+ + " uri content://some_table with query name=some_name and null args\n"
+ + " but got - uri:%1s, where:%2s whereArgs:%3s", uri, where,
+ Arrays.toString(whereArgs));
+ throw new IllegalArgumentException(message);
+ }
+
+ private static String computeTableForSetting(Uri uri, String name) {
+ String table = getValidTableOrThrow(uri);
+
+ if (name != null) {
+ if (sSystemMovedToSecureSettings.contains(name)) {
+ table = TABLE_SECURE;
+ }
+
+ if (sSystemMovedToGlobalSettings.contains(name)) {
+ table = TABLE_GLOBAL;
+ }
+
+ if (sSecureMovedToGlobalSettings.contains(name)) {
+ table = TABLE_GLOBAL;
+ }
+
+ if (sGlobalMovedToSecureSettings.contains(name)) {
+ table = TABLE_SECURE;
}
}
- return bundle;
+
+ return table;
+ }
+ }
+
+ final class SettingsRegistry {
+ private static final String DROPBOX_TAG_USERLOG = "restricted_profile_ssaid";
+
+ private static final int SETTINGS_TYPE_GLOBAL = 0;
+ private static final int SETTINGS_TYPE_SYSTEM = 1;
+ private static final int SETTINGS_TYPE_SECURE = 2;
+
+ private static final int SETTINGS_TYPE_MASK = 0xF0000000;
+ private static final int SETTINGS_TYPE_SHIFT = 28;
+
+ private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
+ private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
+ private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
+
+ private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
+
+ private final BackupManager mBackupManager;
+
+ public SettingsRegistry() {
+ mBackupManager = new BackupManager(getContext());
+ migrateAllLegacySettingsIfNeeded();
}
- /**
- * Populates a key in a given (possibly-null) cache.
- */
- public static void populate(SettingsCache cache, ContentValues contentValues) {
- if (cache == null) {
- return;
- }
- String name = contentValues.getAsString(Settings.NameValueTable.NAME);
- if (name == null) {
- Log.w(TAG, "null name populating settings cache.");
- return;
- }
- String value = contentValues.getAsString(Settings.NameValueTable.VALUE);
- cache.populate(name, value);
+ public List<String> getSettingsNamesLocked(int type, int userId) {
+ final int key = makeKey(type, userId);
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ return settingsState.getSettingNamesLocked();
}
- public void populate(String name, String value) {
- synchronized (this) {
- if (value == null || value.length() <= MAX_CACHE_ENTRY_SIZE) {
- put(name, Bundle.forPair(Settings.NameValueTable.VALUE, value));
+ public SettingsState getSettingsLocked(int type, int userId) {
+ final int key = makeKey(type, userId);
+ return peekSettingsStateLocked(key);
+ }
+
+ public void ensureSettingsForUserLocked(int userId) {
+ // Migrate the setting for this user if needed.
+ migrateLegacySettingsForUserIfNeededLocked(userId);
+
+ // Ensure global settings loaded if owner.
+ if (userId == UserHandle.USER_OWNER) {
+ final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ ensureSettingsStateLocked(globalKey);
+ }
+
+ // Ensure secure settings loaded.
+ final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
+ ensureSettingsStateLocked(secureKey);
+
+ // Make sure the secure settings have an Android id set.
+ SettingsState secureSettings = getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
+ ensureSecureSettingAndroidIdSetLocked(secureSettings);
+
+ // Ensure system settings loaded.
+ final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
+ ensureSettingsStateLocked(systemKey);
+
+ // Upgrade the settings to the latest version.
+ UpgradeController upgrader = new UpgradeController(userId);
+ upgrader.upgradeIfNeededLocked();
+ }
+
+ private void ensureSettingsStateLocked(int key) {
+ if (mSettingsStates.get(key) == null) {
+ final int maxBytesPerPackage = getMaxBytesPerPackageForType(getTypeFromKey(key));
+ SettingsState settingsState = new SettingsState(mLock, getSettingsFile(key), key,
+ maxBytesPerPackage);
+ mSettingsStates.put(key, settingsState);
+ }
+ }
+
+ public void removeUserStateLocked(int userId, boolean permanently) {
+ // We always keep the global settings in memory.
+
+ // Nuke system settings.
+ final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
+ final SettingsState systemSettingsState = mSettingsStates.get(systemKey);
+ if (systemSettingsState != null) {
+ if (permanently) {
+ mSettingsStates.remove(systemKey);
+ systemSettingsState.destroyLocked(null);
} else {
- put(name, TOO_LARGE_TO_CACHE_MARKER);
+ systemSettingsState.destroyLocked(new Runnable() {
+ @Override
+ public void run() {
+ mSettingsStates.remove(systemKey);
+ }
+ });
+ }
+ }
+
+ // Nuke secure settings.
+ final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
+ final SettingsState secureSettingsState = mSettingsStates.get(secureKey);
+ if (secureSettingsState != null) {
+ if (permanently) {
+ mSettingsStates.remove(secureKey);
+ secureSettingsState.destroyLocked(null);
+ } else {
+ secureSettingsState.destroyLocked(new Runnable() {
+ @Override
+ public void run() {
+ mSettingsStates.remove(secureKey);
+ }
+ });
}
}
}
- /**
- * For suppressing duplicate/redundant settings inserts early,
- * checking our cache first (but without faulting it in),
- * before going to sqlite with the mutation.
- */
- public static boolean isRedundantSetValue(SettingsCache cache, String name, String value) {
- if (cache == null) return false;
- synchronized (cache) {
- Bundle bundle = cache.get(name);
- if (bundle == null) return false;
- String oldValue = bundle.getPairValue();
- if (oldValue == null && value == null) return true;
- if ((oldValue == null) != (value == null)) return false;
- return oldValue.equals(value);
+ public boolean insertSettingLocked(int type, int userId, String name, String value,
+ String packageName) {
+ final int key = makeKey(type, userId);
+
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ final boolean success = settingsState.insertSettingLocked(name, value, packageName);
+
+ if (success) {
+ notifyForSettingsChange(key, name);
+ }
+ return success;
+ }
+
+ public boolean deleteSettingLocked(int type, int userId, String name) {
+ final int key = makeKey(type, userId);
+
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ final boolean success = settingsState.deleteSettingLocked(name);
+
+ if (success) {
+ notifyForSettingsChange(key, name);
+ }
+ return success;
+ }
+
+ public Setting getSettingLocked(int type, int userId, String name) {
+ final int key = makeKey(type, userId);
+
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ return settingsState.getSettingLocked(name);
+ }
+
+ public boolean updateSettingLocked(int type, int userId, String name, String value,
+ String packageName) {
+ final int key = makeKey(type, userId);
+
+ SettingsState settingsState = peekSettingsStateLocked(key);
+ final boolean success = settingsState.updateSettingLocked(name, value, packageName);
+
+ if (success) {
+ notifyForSettingsChange(key, name);
+ }
+
+ return success;
+ }
+
+ public void onPackageRemovedLocked(String packageName, int userId) {
+ final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ SettingsState globalSettings = mSettingsStates.get(globalKey);
+ globalSettings.onPackageRemovedLocked(packageName);
+
+ final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
+ SettingsState secureSettings = mSettingsStates.get(secureKey);
+ secureSettings.onPackageRemovedLocked(packageName);
+
+ final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
+ SettingsState systemSettings = mSettingsStates.get(systemKey);
+ systemSettings.onPackageRemovedLocked(packageName);
+ }
+
+ private SettingsState peekSettingsStateLocked(int key) {
+ SettingsState settingsState = mSettingsStates.get(key);
+ if (settingsState != null) {
+ return settingsState;
+ }
+
+ ensureSettingsForUserLocked(getUserIdFromKey(key));
+ return mSettingsStates.get(key);
+ }
+
+ private void migrateAllLegacySettingsIfNeeded() {
+ synchronized (mLock) {
+ final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ File globalFile = getSettingsFile(key);
+ if (globalFile.exists()) {
+ return;
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ List<UserInfo> users = mUserManager.getUsers(true);
+
+ final int userCount = users.size();
+ for (int i = 0; i < userCount; i++) {
+ final int userId = users.get(i).id;
+
+ DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
+ SQLiteDatabase database = dbHelper.getWritableDatabase();
+ migrateLegacySettingsForUserLocked(dbHelper, database, userId);
+
+ // Upgrade to the latest version.
+ UpgradeController upgrader = new UpgradeController(userId);
+ upgrader.upgradeIfNeededLocked();
+
+ // Drop from memory if not a running user.
+ if (!mUserManager.isUserRunning(new UserHandle(userId))) {
+ removeUserStateLocked(userId, false);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
+ // Every user has secure settings and if no file we need to migrate.
+ final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
+ File secureFile = getSettingsFile(secureKey);
+ if (secureFile.exists()) {
+ return;
+ }
+
+ DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
+ SQLiteDatabase database = dbHelper.getWritableDatabase();
+
+ migrateLegacySettingsForUserLocked(dbHelper, database, userId);
+ }
+
+ private void migrateLegacySettingsForUserLocked(DatabaseHelper dbHelper,
+ SQLiteDatabase database, int userId) {
+ // Move over the global settings if owner.
+ if (userId == UserHandle.USER_OWNER) {
+ final int globalKey = makeKey(SETTINGS_TYPE_GLOBAL, userId);
+ ensureSettingsStateLocked(globalKey);
+ SettingsState globalSettings = mSettingsStates.get(globalKey);
+ migrateLegacySettingsLocked(globalSettings, database, TABLE_GLOBAL);
+ globalSettings.persistSyncLocked();
+ }
+
+ // Move over the secure settings.
+ final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
+ ensureSettingsStateLocked(secureKey);
+ SettingsState secureSettings = mSettingsStates.get(secureKey);
+ migrateLegacySettingsLocked(secureSettings, database, TABLE_SECURE);
+ ensureSecureSettingAndroidIdSetLocked(secureSettings);
+ secureSettings.persistSyncLocked();
+
+ // Move over the system settings.
+ final int systemKey = makeKey(SETTINGS_TYPE_SYSTEM, userId);
+ ensureSettingsStateLocked(systemKey);
+ SettingsState systemSettings = mSettingsStates.get(systemKey);
+ migrateLegacySettingsLocked(systemSettings, database, TABLE_SYSTEM);
+ systemSettings.persistSyncLocked();
+
+ // Drop the database as now all is moved and persisted.
+ if (DROP_DATABASE_ON_MIGRATION) {
+ dbHelper.dropDatabase();
+ } else {
+ dbHelper.backupDatabase();
+ }
+ }
+
+ private void migrateLegacySettingsLocked(SettingsState settingsState,
+ SQLiteDatabase database, String table) {
+ SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
+ queryBuilder.setTables(table);
+
+ Cursor cursor = queryBuilder.query(database, ALL_COLUMNS,
+ null, null, null, null, null);
+
+ if (cursor == null) {
+ return;
+ }
+
+ try {
+ if (!cursor.moveToFirst()) {
+ return;
+ }
+
+ final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
+ final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+
+ settingsState.setVersionLocked(database.getVersion());
+
+ while (!cursor.isAfterLast()) {
+ String name = cursor.getString(nameColumnIdx);
+ String value = cursor.getString(valueColumnIdx);
+ settingsState.insertSettingLocked(name, value,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ cursor.moveToNext();
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ private void ensureSecureSettingAndroidIdSetLocked(SettingsState secureSettings) {
+ Setting value = secureSettings.getSettingLocked(Settings.Secure.ANDROID_ID);
+
+ if (value != null) {
+ return;
+ }
+
+ final int userId = getUserIdFromKey(secureSettings.mKey);
+
+ final UserInfo user;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ user = mUserManager.getUserInfo(userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ if (user == null) {
+ // Can happen due to races when deleting users - treat as benign.
+ return;
+ }
+
+ String androidId = Long.toHexString(new SecureRandom().nextLong());
+ secureSettings.insertSettingLocked(Settings.Secure.ANDROID_ID, androidId,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+
+ Slog.d(LOG_TAG, "Generated and saved new ANDROID_ID [" + androidId
+ + "] for user " + userId);
+
+ // Write a drop box entry if it's a restricted profile
+ if (user.isRestricted()) {
+ DropBoxManager dbm = (DropBoxManager) getContext().getSystemService(
+ Context.DROPBOX_SERVICE);
+ if (dbm != null && dbm.isTagEnabled(DROPBOX_TAG_USERLOG)) {
+ dbm.addText(DROPBOX_TAG_USERLOG, System.currentTimeMillis()
+ + "," + DROPBOX_TAG_USERLOG + "," + androidId + "\n");
+ }
+ }
+ }
+
+ private void notifyForSettingsChange(int key, String name) {
+ // Update the system property *first*, so if someone is listening for
+ // a notification and then using the contract class to get their data,
+ // the system property will be updated and they'll get the new data.
+
+ boolean backedUpDataChanged = false;
+ String property = null;
+ if (isGlobalSettingsKey(key)) {
+ property = Settings.Global.SYS_PROP_SETTING_VERSION;
+ backedUpDataChanged = true;
+ } else if (isSecureSettingsKey(key)) {
+ property = Settings.Secure.SYS_PROP_SETTING_VERSION;
+ backedUpDataChanged = true;
+ } else if (isSystemSettingsKey(key)) {
+ property = Settings.System.SYS_PROP_SETTING_VERSION;
+ backedUpDataChanged = true;
+ }
+
+ if (property != null) {
+ final long version = SystemProperties.getLong(property, 0) + 1;
+ SystemProperties.set(property, Long.toString(version));
+ if (DEBUG) {
+ Slog.v(LOG_TAG, "System property " + property + "=" + version);
+ }
+ }
+
+ // Inform the backup manager about a data change
+ if (backedUpDataChanged) {
+ mBackupManager.dataChanged();
+ }
+
+ // Now send the notification through the content framework.
+
+ final int userId = getUserIdFromKey(key);
+ Uri uri = getNotificationUriFor(key, name);
+
+ sendNotify(uri, userId);
+ }
+
+ private int makeKey(int type, int userId) {
+ return (type << SETTINGS_TYPE_SHIFT) | userId;
+ }
+
+ private int getTypeFromKey(int key) {
+ return key >> SETTINGS_TYPE_SHIFT;
+ }
+
+ private int getUserIdFromKey(int key) {
+ return key & ~SETTINGS_TYPE_MASK;
+ }
+
+ private boolean isGlobalSettingsKey(int key) {
+ return getTypeFromKey(key) == SETTINGS_TYPE_GLOBAL;
+ }
+
+ private boolean isSystemSettingsKey(int key) {
+ return getTypeFromKey(key) == SETTINGS_TYPE_SYSTEM;
+ }
+
+ private boolean isSecureSettingsKey(int key) {
+ return getTypeFromKey(key) == SETTINGS_TYPE_SECURE;
+ }
+
+ private File getSettingsFile(int key) {
+ if (isGlobalSettingsKey(key)) {
+ final int userId = getUserIdFromKey(key);
+ return new File(Environment.getUserSystemDirectory(userId),
+ SETTINGS_FILE_GLOBAL);
+ } else if (isSystemSettingsKey(key)) {
+ final int userId = getUserIdFromKey(key);
+ return new File(Environment.getUserSystemDirectory(userId),
+ SETTINGS_FILE_SYSTEM);
+ } else if (isSecureSettingsKey(key)) {
+ final int userId = getUserIdFromKey(key);
+ return new File(Environment.getUserSystemDirectory(userId),
+ SETTINGS_FILE_SECURE);
+ } else {
+ throw new IllegalArgumentException("Invalid settings key:" + key);
+ }
+ }
+
+ private Uri getNotificationUriFor(int key, String name) {
+ if (isGlobalSettingsKey(key)) {
+ return (name != null) ? Uri.withAppendedPath(Settings.Global.CONTENT_URI, name)
+ : Settings.Global.CONTENT_URI;
+ } else if (isSecureSettingsKey(key)) {
+ return (name != null) ? Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name)
+ : Settings.Secure.CONTENT_URI;
+ } else if (isSystemSettingsKey(key)) {
+ return (name != null) ? Uri.withAppendedPath(Settings.System.CONTENT_URI, name)
+ : Settings.System.CONTENT_URI;
+ } else {
+ throw new IllegalArgumentException("Invalid settings key:" + key);
+ }
+ }
+
+ private int getMaxBytesPerPackageForType(int type) {
+ switch (type) {
+ case SETTINGS_TYPE_GLOBAL:
+ case SETTINGS_TYPE_SECURE: {
+ return SettingsState.MAX_BYTES_PER_APP_PACKAGE_UNLIMITED;
+ }
+
+ default: {
+ return SettingsState.MAX_BYTES_PER_APP_PACKAGE_LIMITED;
+ }
+ }
+ }
+
+ private final class UpgradeController {
+ private static final int SETTINGS_VERSION = 118;
+
+ private final int mUserId;
+
+ public UpgradeController(int userId) {
+ mUserId = userId;
+ }
+
+ public void upgradeIfNeededLocked() {
+ // The version of all settings for a user is the same (all users have secure).
+ SettingsState secureSettings = getSettingsLocked(
+ SettingsRegistry.SETTINGS_TYPE_SECURE, mUserId);
+
+ // Try an update from the current state.
+ final int oldVersion = secureSettings.getVersionLocked();
+ final int newVersion = SETTINGS_VERSION;
+
+ // If up do data - done.
+ if (oldVersion == newVersion) {
+ return;
+ }
+
+ // Try to upgrade.
+ final int curVersion = onUpgradeLocked(mUserId, oldVersion, newVersion);
+
+ // If upgrade failed start from scratch and upgrade.
+ if (curVersion != newVersion) {
+ // Drop state we have for this user.
+ removeUserStateLocked(mUserId, true);
+
+ // Recreate the database.
+ DatabaseHelper dbHelper = new DatabaseHelper(getContext(), mUserId);
+ SQLiteDatabase database = dbHelper.getWritableDatabase();
+ dbHelper.recreateDatabase(database, newVersion, curVersion, oldVersion);
+
+ // Migrate the settings for this user.
+ migrateLegacySettingsForUserLocked(dbHelper, database, mUserId);
+
+ // Now upgrade should work fine.
+ onUpgradeLocked(mUserId, oldVersion, newVersion);
+ }
+
+ // Set the global settings version if owner.
+ if (mUserId == UserHandle.USER_OWNER) {
+ SettingsState globalSettings = getSettingsLocked(
+ SettingsRegistry.SETTINGS_TYPE_GLOBAL, mUserId);
+ globalSettings.setVersionLocked(newVersion);
+ }
+
+ // Set the secure settings version.
+ secureSettings.setVersionLocked(newVersion);
+
+ // Set the system settings version.
+ SettingsState systemSettings = getSettingsLocked(
+ SettingsRegistry.SETTINGS_TYPE_SYSTEM, mUserId);
+ systemSettings.setVersionLocked(newVersion);
+ }
+
+ private SettingsState getGlobalSettingsLocked() {
+ return getSettingsLocked(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ }
+
+ private SettingsState getSecureSettingsLocked(int userId) {
+ return getSettingsLocked(SETTINGS_TYPE_SECURE, userId);
+ }
+
+ private SettingsState getSystemSettingsLocked(int userId) {
+ return getSettingsLocked(SETTINGS_TYPE_SYSTEM, userId);
+ }
+
+ private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
+ if (DEBUG) {
+ Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
+ + oldVersion + " to version: " + newVersion);
+ }
+
+ // You must perform all necessary mutations to bring the settings
+ // for this user from the old to the new version. When you add a new
+ // upgrade step you *must* update SETTINGS_VERSION.
+
+ /**
+ * This is an example of moving a setting from secure to global.
+ *
+ * int currentVersion = oldVersion;
+ * if (currentVersion == 118) {
+ * // Remove from the secure settings.
+ * SettingsState secureSettings = getSecureSettingsLocked(userId);
+ * String name = "example_setting_to_move";
+ * String value = secureSettings.getSetting(name);
+ * secureSettings.deleteSetting(name);
+ *
+ * // Add to the global settings.
+ * SettingsState globalSettings = getGlobalSettingsLocked();
+ * globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
+ *
+ * // Update the current version.
+ * currentVersion = 119;
+ * }
+ *
+ * // Return the current version.
+ * return currentVersion;
+ */
+
+ return SettingsState.VERSION_UNDEFINED;
}
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
new file mode 100644
index 0000000..0d03ed9
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import libcore.io.IoUtils;
+import libcore.util.Objects;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class contains the state for one type of settings. It is responsible
+ * for saving the state asynchronously to an XML file after a mutation and
+ * loading the from an XML file on construction.
+ * <p>
+ * This class uses the same lock as the settings provider to ensure that
+ * multiple changes made by the settings provider, e,g, upgrade, bulk insert,
+ * etc, are atomically persisted since the asynchronous persistence is using
+ * the same lock to grab the current state to write to disk.
+ * </p>
+ */
+final class SettingsState {
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_PERSISTENCE = false;
+
+ private static final String LOG_TAG = "SettingsState";
+
+ private static final long WRITE_SETTINGS_DELAY_MILLIS = 200;
+ private static final long MAX_WRITE_SETTINGS_DELAY_MILLIS = 2000;
+
+ public static final int MAX_BYTES_PER_APP_PACKAGE_UNLIMITED = -1;
+ public static final int MAX_BYTES_PER_APP_PACKAGE_LIMITED = 20000;
+
+ public static final String SYSTEM_PACKAGE_NAME = "android";
+
+ public static final int VERSION_UNDEFINED = -1;
+
+ private static final String TAG_SETTINGS = "settings";
+ private static final String TAG_SETTING = "setting";
+ private static final String ATTR_PACKAGE = "package";
+
+ private static final String ATTR_VERSION = "version";
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_VALUE = "value";
+
+ private static final String NULL_VALUE = "null";
+
+ private final Object mLock;
+
+ private final Handler mHandler = new MyHandler();
+
+ @GuardedBy("mLock")
+ private final ArrayMap<String, Setting> mSettings = new ArrayMap<>();
+
+ @GuardedBy("mLock")
+ private final ArrayMap<String, Integer> mPackageToMemoryUsage;
+
+ @GuardedBy("mLock")
+ private final int mMaxBytesPerAppPackage;
+
+ @GuardedBy("mLock")
+ private final File mStatePersistFile;
+
+ public final int mKey;
+
+ @GuardedBy("mLock")
+ private int mVersion = VERSION_UNDEFINED;
+
+ @GuardedBy("mLock")
+ private long mLastNotWrittenMutationTimeMillis;
+
+ @GuardedBy("mLock")
+ private boolean mDirty;
+
+ @GuardedBy("mLock")
+ private boolean mWriteScheduled;
+
+ @GuardedBy("mLock")
+ private long mNextId;
+
+ public SettingsState(Object lock, File file, int key, int maxBytesPerAppPackage) {
+ // It is important that we use the same lock as the settings provider
+ // to ensure multiple mutations on this state are atomicaly persisted
+ // as the async persistence should be blocked while we make changes.
+ mLock = lock;
+ mStatePersistFile = file;
+ mKey = key;
+ if (maxBytesPerAppPackage == MAX_BYTES_PER_APP_PACKAGE_LIMITED) {
+ mMaxBytesPerAppPackage = maxBytesPerAppPackage;
+ mPackageToMemoryUsage = new ArrayMap<>();
+ } else {
+ mMaxBytesPerAppPackage = maxBytesPerAppPackage;
+ mPackageToMemoryUsage = null;
+ }
+ synchronized (mLock) {
+ readStateSyncLocked();
+ }
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public int getVersionLocked() {
+ return mVersion;
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public void setVersionLocked(int version) {
+ if (version == mVersion) {
+ return;
+ }
+ mVersion = version;
+
+ scheduleWriteIfNeededLocked();
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public void onPackageRemovedLocked(String packageName) {
+ boolean removedSomething = false;
+
+ final int settingCount = mSettings.size();
+ for (int i = settingCount - 1; i >= 0; i--) {
+ String name = mSettings.keyAt(i);
+ // Settings defined by use are never dropped.
+ if (Settings.System.PUBLIC_SETTINGS.contains(name)
+ || Settings.System.PRIVATE_SETTINGS.contains(name)) {
+ continue;
+ }
+ Setting setting = mSettings.valueAt(i);
+ if (packageName.equals(setting.packageName)) {
+ mSettings.removeAt(i);
+ removedSomething = true;
+ }
+ }
+
+ if (removedSomething) {
+ scheduleWriteIfNeededLocked();
+ }
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public List<String> getSettingNamesLocked() {
+ ArrayList<String> names = new ArrayList<>();
+ final int settingsCount = mSettings.size();
+ for (int i = 0; i < settingsCount; i++) {
+ String name = mSettings.keyAt(i);
+ names.add(name);
+ }
+ return names;
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public Setting getSettingLocked(String name) {
+ if (TextUtils.isEmpty(name)) {
+ return null;
+ }
+ return mSettings.get(name);
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public boolean updateSettingLocked(String name, String value, String packageName) {
+ if (!hasSettingLocked(name)) {
+ return false;
+ }
+
+ return insertSettingLocked(name, value, packageName);
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public boolean insertSettingLocked(String name, String value, String packageName) {
+ if (TextUtils.isEmpty(name)) {
+ return false;
+ }
+
+ Setting oldState = mSettings.get(name);
+ String oldValue = (oldState != null) ? oldState.value : null;
+
+ if (oldState != null) {
+ if (!oldState.update(value, packageName)) {
+ return false;
+ }
+ } else {
+ Setting state = new Setting(name, value, packageName);
+ mSettings.put(name, state);
+ }
+
+ updateMemoryUsagePerPackageLocked(packageName, oldValue, value);
+
+ scheduleWriteIfNeededLocked();
+
+ return true;
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public void persistSyncLocked() {
+ mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
+ doWriteState();
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public boolean deleteSettingLocked(String name) {
+ if (TextUtils.isEmpty(name) || !hasSettingLocked(name)) {
+ return false;
+ }
+
+ Setting oldState = mSettings.remove(name);
+
+ updateMemoryUsagePerPackageLocked(oldState.packageName, oldState.value, null);
+
+ scheduleWriteIfNeededLocked();
+
+ return true;
+ }
+
+ // The settings provider must hold its lock when calling here.
+ public void destroyLocked(Runnable callback) {
+ mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
+ if (callback != null) {
+ if (mDirty) {
+ // Do it without a delay.
+ mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS,
+ callback).sendToTarget();
+ return;
+ }
+ callback.run();
+ }
+ }
+
+ private void updateMemoryUsagePerPackageLocked(String packageName, String oldValue,
+ String newValue) {
+ if (mMaxBytesPerAppPackage == MAX_BYTES_PER_APP_PACKAGE_UNLIMITED) {
+ return;
+ }
+
+ if (SYSTEM_PACKAGE_NAME.equals(packageName)) {
+ return;
+ }
+
+ final int oldValueSize = (oldValue != null) ? oldValue.length() : 0;
+ final int newValueSize = (newValue != null) ? newValue.length() : 0;
+ final int deltaSize = newValueSize - oldValueSize;
+
+ Integer currentSize = mPackageToMemoryUsage.get(packageName);
+ final int newSize = Math.max((currentSize != null)
+ ? currentSize + deltaSize : deltaSize, 0);
+
+ if (newSize > mMaxBytesPerAppPackage) {
+ throw new IllegalStateException("You are adding too many system settings. "
+ + "You should stop using system settings for app specific data"
+ + " package: " + packageName);
+ }
+
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Settings for package: " + packageName
+ + " size: " + newSize + " bytes.");
+ }
+
+ mPackageToMemoryUsage.put(packageName, newSize);
+ }
+
+ private boolean hasSettingLocked(String name) {
+ return mSettings.indexOfKey(name) >= 0;
+ }
+
+ private void scheduleWriteIfNeededLocked() {
+ // If dirty then we have a write already scheduled.
+ if (!mDirty) {
+ mDirty = true;
+ writeStateAsyncLocked();
+ }
+ }
+
+ private void writeStateAsyncLocked() {
+ final long currentTimeMillis = SystemClock.uptimeMillis();
+
+ if (mWriteScheduled) {
+ mHandler.removeMessages(MyHandler.MSG_PERSIST_SETTINGS);
+
+ // If enough time passed, write without holding off anymore.
+ final long timeSinceLastNotWrittenMutationMillis = currentTimeMillis
+ - mLastNotWrittenMutationTimeMillis;
+ if (timeSinceLastNotWrittenMutationMillis >= MAX_WRITE_SETTINGS_DELAY_MILLIS) {
+ mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS).sendToTarget();
+ return;
+ }
+
+ // Hold off a bit more as settings are frequently changing.
+ final long maxDelayMillis = Math.max(mLastNotWrittenMutationTimeMillis
+ + MAX_WRITE_SETTINGS_DELAY_MILLIS - currentTimeMillis, 0);
+ final long writeDelayMillis = Math.min(WRITE_SETTINGS_DELAY_MILLIS, maxDelayMillis);
+
+ Message message = mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS);
+ mHandler.sendMessageDelayed(message, writeDelayMillis);
+ } else {
+ mLastNotWrittenMutationTimeMillis = currentTimeMillis;
+ Message message = mHandler.obtainMessage(MyHandler.MSG_PERSIST_SETTINGS);
+ mHandler.sendMessageDelayed(message, WRITE_SETTINGS_DELAY_MILLIS);
+ mWriteScheduled = true;
+ }
+ }
+
+ private void doWriteState() {
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSIST START]");
+ }
+
+ AtomicFile destination = new AtomicFile(mStatePersistFile);
+
+ final int version;
+ final ArrayMap<String, Setting> settings;
+
+ synchronized (mLock) {
+ version = mVersion;
+ settings = new ArrayMap<>(mSettings);
+ mDirty = false;
+ mWriteScheduled = false;
+ }
+
+ FileOutputStream out = null;
+ try {
+ out = destination.startWrite();
+
+ XmlSerializer serializer = Xml.newSerializer();
+ serializer.setOutput(out, "utf-8");
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_SETTINGS);
+ serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+
+ final int settingCount = settings.size();
+ for (int i = 0; i < settingCount; i++) {
+ Setting setting = settings.valueAt(i);
+
+ serializer.startTag(null, TAG_SETTING);
+ serializer.attribute(null, ATTR_ID, setting.getId());
+ serializer.attribute(null, ATTR_NAME, setting.getName());
+ serializer.attribute(null, ATTR_VALUE, packValue(setting.getValue()));
+ serializer.attribute(null, ATTR_PACKAGE, packValue(setting.getPackageName()));
+ serializer.endTag(null, TAG_SETTING);
+
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSISTED]" + setting.getName() + "=" + setting.getValue());
+ }
+ }
+
+ serializer.endTag(null, TAG_SETTINGS);
+ serializer.endDocument();
+ destination.finishWrite(out);
+
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSIST END]");
+ }
+
+ } catch (IOException e) {
+ Slog.w(LOG_TAG, "Failed to write settings, restoring backup", e);
+ destination.failWrite(out);
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+
+ private void readStateSyncLocked() {
+ FileInputStream in;
+ if (!mStatePersistFile.exists()) {
+ return;
+ }
+ try {
+ in = new FileInputStream(mStatePersistFile);
+ } catch (FileNotFoundException fnfe) {
+ Slog.i(LOG_TAG, "No settings state");
+ return;
+ }
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseStateLocked(parser);
+ } catch (XmlPullParserException | IOException ise) {
+ throw new IllegalStateException("Failed parsing settings file: "
+ + mStatePersistFile , ise);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ private void parseStateLocked(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_SETTINGS);
+
+ mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
+
+ parser.next();
+
+ while (parseSettingLocked(parser)) {
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_SETTINGS);
+ }
+
+ private boolean parseSettingLocked(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ skipEmptyTextTags(parser);
+ if (!accept(parser, XmlPullParser.START_TAG, TAG_SETTING)) {
+ return false;
+ }
+
+ String id = parser.getAttributeValue(null, ATTR_ID);
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ String value = parser.getAttributeValue(null, ATTR_VALUE);
+ String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ mSettings.put(name, new Setting(name, unpackValue(value),
+ unpackValue(packageName), id));
+
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[RESTORED] " + name + "=" + value);
+ }
+
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_SETTING);
+
+ return true;
+ }
+
+ private void expect(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (!accept(parser, type, tag)) {
+ throw new XmlPullParserException("Expected event: " + type
+ + " and tag: " + tag + " but got event: " + parser.getEventType()
+ + " and tag:" + parser.getName());
+ }
+ }
+
+ private void skipEmptyTextTags(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ while (accept(parser, XmlPullParser.TEXT, null)
+ && "\n".equals(parser.getText())) {
+ parser.next();
+ }
+ }
+
+ private boolean accept(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (parser.getEventType() != type) {
+ return false;
+ }
+ if (tag != null) {
+ if (!tag.equals(parser.getName())) {
+ return false;
+ }
+ } else if (parser.getName() != null) {
+ return false;
+ }
+ return true;
+ }
+
+ private final class MyHandler extends Handler {
+ public static final int MSG_PERSIST_SETTINGS = 1;
+
+ public MyHandler() {
+ super(BackgroundThread.getHandler().getLooper());
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_PERSIST_SETTINGS: {
+ Runnable callback = (Runnable) message.obj;
+ doWriteState();
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private static String packValue(String value) {
+ if (value == null) {
+ return NULL_VALUE;
+ }
+ return value;
+ }
+
+ private static String unpackValue(String value) {
+ if (NULL_VALUE.equals(value)) {
+ return null;
+ }
+ return value;
+ }
+
+ public final class Setting {
+ private String name;
+ private String value;
+ private String packageName;
+ private String id;
+
+ public Setting(String name, String value, String packageName) {
+ init(name, value, packageName, String.valueOf(mNextId++));
+ }
+
+ public Setting(String name, String value, String packageName, String id) {
+ mNextId = Math.max(mNextId, Long.valueOf(id) + 1);
+ init(name, value, packageName, id);
+ }
+
+ private void init(String name, String value, String packageName, String id) {
+ this.name = name;
+ this.value = value;
+ this.packageName = packageName;
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public boolean update(String value, String packageName) {
+ if (Objects.equal(value, this.value)) {
+ return false;
+ }
+ this.value = value;
+ this.packageName = packageName;
+ this.id = String.valueOf(mNextId++);
+ return true;
+ }
+ }
+}
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
new file mode 100644
index 0000000..01c6ccf
--- /dev/null
+++ b/packages/SettingsProvider/test/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SettingsProviderTest
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/packages/SettingsProvider/test/AndroidManifest.xml b/packages/SettingsProvider/test/AndroidManifest.xml
new file mode 100644
index 0000000..7a86b5f
--- /dev/null
+++ b/packages/SettingsProvider/test/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.providers.setting.test">
+
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+
+ <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.providers.setting.test"
+ android:label="Settings Provider Tests" />
+</manifest>
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
new file mode 100644
index 0000000..8473db4
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+
+import java.util.List;
+
+/**
+ * Base class for the SettingContentProvider tests.
+ */
+abstract class BaseSettingsProviderTest extends AndroidTestCase {
+ protected static final int SETTING_TYPE_GLOBAL = 1;
+ protected static final int SETTING_TYPE_SECURE = 2;
+ protected static final int SETTING_TYPE_SYSTEM = 3;
+
+ protected static final String FAKE_SETTING_NAME = "fake_setting_name";
+ protected static final String FAKE_SETTING_NAME_1 = "fake_setting_name1";
+ protected static final String FAKE_SETTING_VALUE = "fake_setting_value";
+ protected static final String FAKE_SETTING_VALUE_1 = "fake_setting_value_1";
+
+ private static final String[] NAME_VALUE_COLUMNS = new String[] {
+ Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE
+ };
+
+ protected int mSecondaryUserId = UserHandle.USER_OWNER;
+
+ @Override
+ public void setContext(Context context) {
+ super.setContext(context);
+
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ List<UserInfo> users = userManager.getUsers();
+ final int userCount = users.size();
+ for (int i = 0; i < userCount; i++) {
+ UserInfo user = users.get(i);
+ if (!user.isPrimary() && !user.isManagedProfile()) {
+ mSecondaryUserId = user.id;
+ break;
+ }
+ }
+ }
+
+ protected void setStringViaFrontEndApiSetting(int type, String name, String value, int userId) {
+ ContentResolver contentResolver = getContext().getContentResolver();
+
+ switch (type) {
+ case SETTING_TYPE_GLOBAL: {
+ Settings.Global.putStringForUser(contentResolver, name, value, userId);
+ } break;
+
+ case SETTING_TYPE_SECURE: {
+ Settings.Secure.putStringForUser(contentResolver, name, value, userId);
+ } break;
+
+ case SETTING_TYPE_SYSTEM: {
+ Settings.System.putStringForUser(contentResolver, name, value, userId);
+ } break;
+
+ default: {
+ throw new IllegalArgumentException("Invalid type: " + type);
+ }
+ }
+ }
+
+ protected String getStringViaFrontEndApiSetting(int type, String name, int userId) {
+ ContentResolver contentResolver = getContext().getContentResolver();
+
+ switch (type) {
+ case SETTING_TYPE_GLOBAL: {
+ return Settings.Global.getStringForUser(contentResolver, name, userId);
+ }
+
+ case SETTING_TYPE_SECURE: {
+ return Settings.Secure.getStringForUser(contentResolver, name, userId);
+ }
+
+ case SETTING_TYPE_SYSTEM: {
+ return Settings.System.getStringForUser(contentResolver, name, userId);
+ }
+
+ default: {
+ throw new IllegalArgumentException("Invalid type: " + type);
+ }
+ }
+ }
+
+ protected Uri insertStringViaProviderApi(int type, String name, String value,
+ boolean withTableRowUri) {
+ Uri uri = getBaseUriForType(type);
+ if (withTableRowUri) {
+ uri = Uri.withAppendedPath(uri, name);
+ }
+ ContentValues values = new ContentValues();
+ values.put(Settings.NameValueTable.NAME, name);
+ values.put(Settings.NameValueTable.VALUE, value);
+
+ return getContext().getContentResolver().insert(uri, values);
+ }
+
+ protected int deleteStringViaProviderApi(int type, String name) {
+ Uri uri = getBaseUriForType(type);
+ return getContext().getContentResolver().delete(uri, "name=?", new String[]{name});
+ }
+
+ protected int updateStringViaProviderApiSetting(int type, String name, String value) {
+ Uri uri = getBaseUriForType(type);
+ ContentValues values = new ContentValues();
+ values.put(Settings.NameValueTable.NAME, name);
+ values.put(Settings.NameValueTable.VALUE, value);
+ return getContext().getContentResolver().update(uri, values, "name=?",
+ new String[]{name});
+ }
+
+ protected String queryStringViaProviderApi(int type, String name) {
+ return queryStringViaProviderApi(type, name, false, false);
+ }
+
+ protected String queryStringViaProviderApi(int type, String name, boolean queryStringInQuotes,
+ boolean appendNameToUri) {
+ final Uri uri;
+ final String queryString;
+ final String[] queryArgs;
+
+ if (appendNameToUri) {
+ uri = Uri.withAppendedPath(getBaseUriForType(type), name);
+ queryString = null;
+ queryArgs = null;
+ } else {
+ uri = getBaseUriForType(type);
+ queryString = queryStringInQuotes ? "(name=?)" : "name=?";
+ queryArgs = new String[]{name};
+ }
+
+ Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS,
+ queryString, queryArgs, null);
+
+ if (cursor == null) {
+ return null;
+ }
+
+ try {
+ if (cursor.moveToFirst()) {
+ final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE);
+ return cursor.getString(valueColumnIdx);
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return null;
+ }
+
+ protected static Uri getBaseUriForType(int type) {
+ switch (type) {
+ case SETTING_TYPE_GLOBAL: {
+ return Settings.Global.CONTENT_URI;
+ }
+
+ case SETTING_TYPE_SECURE: {
+ return Settings.Secure.CONTENT_URI;
+ }
+
+ case SETTING_TYPE_SYSTEM: {
+ return Settings.System.CONTENT_URI;
+ }
+
+ default: {
+ throw new IllegalArgumentException("Invalid type: " + type);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java
new file mode 100644
index 0000000..d581f3b
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderPerformanceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+* Performance tests for the SettingContentProvider.
+*/
+public class SettingsProviderPerformanceTest extends BaseSettingsProviderTest {
+ private static final String LOG_TAG = "SettingsProviderPerformanceTest";
+
+ private static final int ITERATION_COUNT = 100;
+
+ private static final int MICRO_SECONDS_IN_MILLISECOND = 1000;
+
+ private static final long MAX_AVERAGE_SET_AND_GET_SETTING_DURATION_MILLIS = 20;
+
+ public void testSetAndGetPerformanceForGlobalViaFrontEndApi() throws Exception {
+ // Start with a clean slate.
+ insertStringViaProviderApi(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
+
+ final long startTimeMicro = SystemClock.currentTimeMicro();
+
+ try {
+ for (int i = 0; i < ITERATION_COUNT; i++) {
+ // Set the setting to its first value.
+ updateStringViaProviderApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE);
+
+ // Make sure the setting changed.
+ String firstValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ assertEquals("Setting value didn't change", FAKE_SETTING_VALUE, firstValue);
+
+ // Set the setting to its second value.
+ updateStringViaProviderApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE_1);
+
+ // Make sure the setting changed.
+ String secondValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ assertEquals("Setting value didn't change", FAKE_SETTING_VALUE_1, secondValue);
+ }
+ } finally {
+ // Clean up.
+ deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME);
+ }
+
+ final long elapsedTimeMicro = SystemClock.currentTimeMicro() - startTimeMicro;
+
+ final long averageTimePerIterationMillis = (long) ((((float) elapsedTimeMicro)
+ / ITERATION_COUNT) / MICRO_SECONDS_IN_MILLISECOND);
+
+ Log.i(LOG_TAG, "Average time to set and get setting via provider APIs: "
+ + averageTimePerIterationMillis + " ms");
+
+ assertTrue("Setting and getting a settings takes too long.", averageTimePerIterationMillis
+ < MAX_AVERAGE_SET_AND_GET_SETTING_DURATION_MILLIS);
+ }
+
+ public void testSetAndGetPerformanceForGlobalViaProviderApi() throws Exception {
+ // Start with a clean slate.
+ deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME);
+
+ final long startTimeMicro = SystemClock.currentTimeMicro();
+
+ try {
+ for (int i = 0; i < ITERATION_COUNT; i++) {
+ // Set the setting to its first value.
+ setStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE, UserHandle.USER_OWNER);
+
+ // Make sure the setting changed.
+ String firstValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ assertEquals("Setting value didn't change", FAKE_SETTING_VALUE, firstValue);
+
+ // Set the setting to its second value.
+ setStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE_1, UserHandle.USER_OWNER);
+
+ // Make sure the setting changed.
+ String secondValue = getStringViaFrontEndApiSetting(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, UserHandle.USER_OWNER);
+ assertEquals("Setting value didn't change", FAKE_SETTING_VALUE_1, secondValue);
+ }
+ } finally {
+ // Clean up.
+ deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME);
+ }
+
+ final long elapsedTimeMicro = SystemClock.currentTimeMicro() - startTimeMicro;
+
+ final long averageTimePerIterationMillis = (long) ((((float) elapsedTimeMicro)
+ / ITERATION_COUNT) / MICRO_SECONDS_IN_MILLISECOND);
+
+ Log.i(LOG_TAG, "Average time to set and get setting via front-eng APIs: "
+ + averageTimePerIterationMillis + " ms");
+
+ assertTrue("Setting and getting a settings takes too long.", averageTimePerIterationMillis
+ < MAX_AVERAGE_SET_AND_GET_SETTING_DURATION_MILLIS);
+ }
+}
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
new file mode 100644
index 0000000..b89fb10
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tests for the SettingContentProvider.
+ *
+ * Before you run this test you must add a secondary user.
+ */
+public class SettingsProviderTest extends BaseSettingsProviderTest {
+ private static final String LOG_TAG = "SettingsProviderTest";
+
+ private static final long WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec
+
+ private static final String[] NAME_VALUE_COLUMNS = new String[]{
+ Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE
+ };
+
+ private final Object mLock = new Object();
+
+ public void testSetAndGetGlobalViaFrontEndApiForOwnerUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_OWNER);
+ }
+
+ public void testSetAndGetGlobalViaFrontEndApiForNonOwnerUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ Log.w(LOG_TAG, "No secondary user. Skipping "
+ + "testSetAndGetGlobalViaFrontEndApiForNonOwnerUser");
+ return;
+ }
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, mSecondaryUserId);
+ }
+
+ public void testSetAndGetSecureViaFrontEndApiForOwnerUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_OWNER);
+ }
+
+ public void testSetAndGetSecureViaFrontEndApiForNonOwnerUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ Log.w(LOG_TAG, "No secondary user. Skipping "
+ + "testSetAndGetSecureViaFrontEndApiForNonOwnerUser");
+ return;
+ }
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, mSecondaryUserId);
+ }
+
+ public void testSetAndGetSystemViaFrontEndApiForOwnerUser() throws Exception {
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_OWNER);
+ }
+
+ public void testSetAndGetSystemViaFrontEndApiForNonOwnerUser() throws Exception {
+ if (mSecondaryUserId == UserHandle.USER_OWNER) {
+ Log.w(LOG_TAG, "No secondary user. Skipping "
+ + "testSetAndGetSystemViaFrontEndApiForNonOwnerUser");
+ return;
+ }
+ performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, mSecondaryUserId);
+ }
+
+ public void testSetAndGetGlobalViaProviderApi() throws Exception {
+ performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_GLOBAL);
+ }
+
+ public void testSetAndGetSecureViaProviderApi() throws Exception {
+ performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SECURE);
+ }
+
+ public void testSetAndGetSystemViaProviderApi() throws Exception {
+ performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM);
+ }
+
+ public void testSelectAllGlobalViaProviderApi() throws Exception {
+ setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
+ try {
+ queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_GLOBAL,
+ FAKE_SETTING_NAME);
+ } finally {
+ deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME);
+ }
+ }
+
+ public void testSelectAllSecureViaProviderApi() throws Exception {
+ setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SECURE,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
+ try {
+ queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SECURE,
+ FAKE_SETTING_NAME);
+ } finally {
+ deleteStringViaProviderApi(SETTING_TYPE_SECURE, FAKE_SETTING_NAME);
+ }
+ }
+
+ public void testSelectAllSystemViaProviderApi() throws Exception {
+ setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SYSTEM,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE, true);
+ try {
+ queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SYSTEM,
+ FAKE_SETTING_NAME);
+ } finally {
+ deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
+ }
+ }
+
+ public void testQueryUpdateDeleteGlobalViaProviderApi() throws Exception {
+ doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_GLOBAL);
+ }
+
+ public void testQueryUpdateDeleteSecureViaProviderApi() throws Exception {
+ doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SECURE);
+ }
+
+ public void testQueryUpdateDeleteSystemViaProviderApi() throws Exception {
+ doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SYSTEM);
+ }
+
+ public void testBulkInsertGlobalViaProviderApi() throws Exception {
+ toTestBulkInsertViaProviderApiForType(SETTING_TYPE_GLOBAL);
+ }
+
+ public void testBulkInsertSystemViaProviderApi() throws Exception {
+ toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SYSTEM);
+ }
+
+ public void testBulkInsertSecureViaProviderApi() throws Exception {
+ toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SECURE);
+ }
+
+ public void testAppCannotRunsSystemOutOfMemoryWritingSystemSettings() throws Exception {
+ int insertedCount = 0;
+ try {
+ for (; insertedCount < 1200; insertedCount++) {
+ Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount);
+ insertStringViaProviderApi(SETTING_TYPE_SYSTEM,
+ String.valueOf(insertedCount), FAKE_SETTING_VALUE, false);
+ }
+ fail("Adding app specific settings must be bound.");
+ } catch (Exception e) {
+ for (; insertedCount >= 0; insertedCount--) {
+ Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount);
+ deleteStringViaProviderApi(SETTING_TYPE_SYSTEM,
+ String.valueOf(insertedCount));
+ }
+ }
+ }
+
+ public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception {
+ doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL);
+ }
+
+ public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception {
+ doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE);
+ }
+
+ public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception {
+ doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM);
+ }
+
+ public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception {
+ // Make sure we have a clean slate.
+ deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
+
+ try {
+ // Insert the setting.
+ final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE, false);
+ Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM),
+ FAKE_SETTING_NAME);
+ assertEquals("Did not get expected Uri.", expectUri, uri);
+
+ // Make sure the first setting is there.
+ String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME,
+ false, true);
+ assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
+ } finally {
+ // Clean up.
+ deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME);
+ }
+ }
+
+ private void doTestQueryStringInBracketsViaProviderApiForType(int type) {
+ // Make sure we have a clean slate.
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
+
+ try {
+ // Insert the setting.
+ final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE, false);
+ Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
+ assertEquals("Did not get expected Uri.", expectUri, uri);
+
+ // Make sure the first setting is there.
+ String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false);
+ assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue);
+ } finally {
+ // Clean up.
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
+ }
+ }
+
+ private void toTestBulkInsertViaProviderApiForType(int type) {
+ // Make sure we have a clean slate.
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
+
+ try {
+ Uri uri = getBaseUriForType(type);
+ ContentValues[] allValues = new ContentValues[2];
+
+ // Insert the first setting.
+ ContentValues firstValues = new ContentValues();
+ firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME);
+ firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE);
+ allValues[0] = firstValues;
+
+ // Insert the first setting.
+ ContentValues secondValues = new ContentValues();
+ secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1);
+ secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1);
+ allValues[1] = secondValues;
+
+ // Verify insertion count.
+ final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues);
+ assertSame("Couldn't insert both values", 2, insertCount);
+
+ // Make sure the first setting is there.
+ String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
+ assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue);
+
+ // Make sure the second setting is there.
+ String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1);
+ assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue);
+ } finally {
+ // Clean up.
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1);
+ }
+ }
+
+ private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception {
+ // Make sure it is not there.
+ deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
+
+ // Now selection should return nothing.
+ String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
+ assertNull("Setting should not be present.", value);
+
+ // Insert the setting.
+ Uri uri = insertStringViaProviderApi(type,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false);
+ Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME);
+ assertEquals("Did not get expected Uri.", expectUri, uri);
+
+ // Now selection should return the setting.
+ value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
+ assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value);
+
+ // Update the setting.
+ final int changeCount = updateStringViaProviderApiSetting(type,
+ FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1);
+ assertEquals("Did not get expected change count.", 1, changeCount);
+
+ // Now selection should return the new setting.
+ value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
+ assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value);
+
+ // Delete the setting.
+ final int deletedCount = deleteStringViaProviderApi(type,
+ FAKE_SETTING_NAME);
+ assertEquals("Did not get expected deleted count", 1, deletedCount);
+
+ // Now selection should return nothing.
+ value = queryStringViaProviderApi(type, FAKE_SETTING_NAME);
+ assertNull("Setting should not be present.", value);
+ }
+
+ private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId)
+ throws Exception {
+ try {
+ // Change the setting and assert a successful change.
+ setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE, userId);
+ } finally {
+ // Remove the setting.
+ setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId);
+ }
+ }
+
+ private void performSetAndGetSettingTestViaProviderApi(int type)
+ throws Exception {
+ try {
+ // Change the setting and assert a successful change.
+ setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME,
+ FAKE_SETTING_VALUE, true);
+ } finally {
+ // Remove the setting.
+ setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null,
+ true);
+ }
+ }
+
+ private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type,
+ final String name, final String value, final int userId) throws Exception {
+ setSettingAndAssertSuccessfulChange(new Runnable() {
+ @Override
+ public void run() {
+ setStringViaFrontEndApiSetting(type, name, value, userId);
+ }
+ }, type, name, value, userId);
+ }
+
+ private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type,
+ final String name, final String value, final boolean withTableRowUri)
+ throws Exception {
+ setSettingAndAssertSuccessfulChange(new Runnable() {
+ @Override
+ public void run() {
+ insertStringViaProviderApi(type, name, value, withTableRowUri);
+ }
+ }, type, name, value, UserHandle.USER_OWNER);
+ }
+
+ private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type,
+ final String name, final String value, final int userId) throws Exception {
+ ContentResolver contentResolver = getContext().getContentResolver();
+
+ final Uri settingUri = getBaseUriForType(type);
+
+ final AtomicBoolean success = new AtomicBoolean();
+
+ ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+ public void onChange(boolean selfChange, Uri changeUri, int changeId) {
+ Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")");
+ assertEquals("Wrong change Uri", changeUri, settingUri);
+ assertEquals("Wrong user id", userId, changeId);
+ String changeValue = getStringViaFrontEndApiSetting(type, name, userId);
+ assertEquals("Wrong setting value", value, changeValue);
+
+ success.set(true);
+
+ synchronized (mLock) {
+ mLock.notifyAll();
+ }
+ }
+ };
+
+ contentResolver.registerContentObserver(settingUri, false, contentObserver, userId);
+
+ try {
+ setCommand.run();
+
+ final long startTimeMillis = SystemClock.uptimeMillis();
+ synchronized (mLock) {
+ if (success.get()) {
+ return;
+ }
+ final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+ if (elapsedTimeMillis > WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) {
+ fail("Could not change setting for "
+ + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms");
+ }
+ final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS
+ - elapsedTimeMillis;
+ try {
+ mLock.wait(remainingTimeMillis);
+ } catch (InterruptedException ie) {
+ /* ignore */
+ }
+ }
+ } finally {
+ contentResolver.unregisterContentObserver(contentObserver);
+ }
+ }
+
+ private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type,
+ String name) {
+ Uri uri = getBaseUriForType(type);
+
+ Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS,
+ null, null, null);
+
+ if (cursor == null || !cursor.moveToFirst()) {
+ fail("Nothing selected");
+ }
+
+ try {
+ final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME);
+
+ while (cursor.moveToNext()) {
+ String currentName = cursor.getString(nameColumnIdx);
+ if (name.equals(currentName)) {
+ return;
+ }
+ }
+
+ fail("Not found setting: " + name);
+ } finally {
+ cursor.close();
+ }
+ }
+}
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 2904cbb..0c42cab 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -17,9 +17,9 @@
<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">"Shell-interfazea"</string>
- <string name="bugreport_finished_title" msgid="2293711546892863898">"Programa-akatsen txostena jaso da"</string>
+ <string name="bugreport_finished_title" msgid="2293711546892863898">"Akatsen txostena jaso da"</string>
<string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Programa-akatsen txostena partekatzeko, pasatu hatza ezkerrera"</string>
- <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Programa-akatsen txostena partekatzeko, ukitu"</string>
- <string name="bugreport_confirm" msgid="5130698467795669780">"Programa-akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Programa-akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Akatsen txostena partekatzeko, ukitu"</string>
+ <string name="bugreport_confirm" msgid="5130698467795669780">"Akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Erakutsi mezu hau hurrengoan"</string>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
new file mode 100644
index 0000000..28d2e26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
@@ -0,0 +1,41 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:alpha=".3"
+ android:width="64dp" >
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13.8,11.1L17.0,11.1l0.0,2.0l-1.2,0.0l4.5,4.5c1.1,-1.6 1.7,-3.5 1.7,-5.5c0.0,-5.5 -4.5,-10.0 -10.0,-10.0c-2.0,0.0 -3.9,0.6 -5.5,1.7L13.8,11.1z" />
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13.0,13.1L7.0,13.1l0.0,-2.0l4.0,0.0L4.9,5.0C3.1,6.8 2.0,9.3 2.0,12.1c0.0,5.5 4.5,10.0 10.0,10.0c2.8,0.0 5.3,-1.1 7.1,-2.9L13.0,13.1z" />
+
+ <group
+ android:pivotX="12.0"
+ android:pivotY="12.0"
+ android:rotation="45.0"
+ android:translateX="0.5"
+ android:translateY="0.5" >
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M-2.8,11.8l28.3,0.0l0.0,2.0l-28.3,0.0z" />
+ </group>
+
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
new file mode 100644
index 0000000..7617ec4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_dnd.xml b/packages/SystemUI/res/drawable/stat_sys_dnd.xml
new file mode 100644
index 0000000..9361bc0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_dnd.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="2.5dp"
+ android:insetRight="2.5dp">
+ <vector
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1d8cb46..f7bbce0 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -79,7 +79,8 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="match_parent"
android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:layout_marginBottom="@dimen/close_handle_underlap" />
+ android:layout_marginBottom="@dimen/close_handle_underlap"
+ android:importantForAccessibility="no" />
<ViewStub
android:id="@+id/keyguard_user_switcher"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 6d3f976..532e1b7 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -22,9 +22,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:focusable="true"
- android:fitsSystemWindows="true"
- android:descendantFocusability="afterDescendants">
+ android:fitsSystemWindows="true">
<com.android.systemui.statusbar.BackDropView
android:id="@+id/backdrop"
@@ -45,7 +43,8 @@
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_behind"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no" />
<include layout="@layout/status_bar"
android:layout_width="match_parent"
@@ -82,6 +81,7 @@
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no" />
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 27353ff..33c1899 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -40,6 +40,16 @@
android:clipChildren="false" />
</FrameLayout>
+ <View
+ android:id="@+id/zen_embedded_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:visibility="gone"
+ android:layout_marginStart="@dimen/qs_panel_padding"
+ android:layout_marginEnd="@dimen/qs_panel_padding"
+ android:layout_marginBottom="@dimen/qs_panel_padding"
+ android:background="#4dffffff" />
+
<RelativeLayout
android:id="@+id/zen_subhead"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 79c37e8..2d458fa 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Program Info"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Jou onlangse skerms verskyn hier"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Maak onlangse programme toe"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 skerm in Oorsig"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skerms in Oorsig"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d skerms in Oorsig</item>
+ <item quantity="one">1 skerm in Oorsig</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen kennisgewings"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Voortdurend"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Kennisgewings"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ontsluit"</string>
<string name="phone_label" msgid="2320074140205331708">"maak foon oop"</string>
<string name="camera_label" msgid="7261107956054836961">"maak kamera oop"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Versoenbaarheid-zoem se knoppie."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoem kleiner na groter skerm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth gekoppel."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiele warmkol aangeskakel."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Uitsaai van skerm gestaak."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Skermhelderheid"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G-data is af"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-data is af"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Sellulêre data is af"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data is af"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Jou toestel het data afgeskakel, want dit het die limiet bereik wat jy gestel het.\n\nAs dit weer aangeskakel word, kan dit tot heffings van jou diensverskaffer af lei."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Skakel data aan"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data is laat wag"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data is laat wag"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Sellulêre data is onderbreek"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is onderbreek"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Omdat die gestelde dataperk bereik is, het die toestel datagebruik vir die res van hierdie siklus onderbreek.\n\nAs dit hervat word, kan dit tot heffings deur jou diensverskaffer lei."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Hervat"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Geen internetverbinding nie"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi gekoppel"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Soek vir GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Versteek <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Dit sal verskyn die volgende keer wanneer jy dit in instellings aanskakel."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Versteek"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wil die volumedialoog wees."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Laat toe"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Weier"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 6db37cc..3248d7a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 ማያ ገጽ በአጠቃላይ እይታ ውስጥ"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ማያ ገጾች በአጠቃላይ እይታ ውስጥ"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"በመካሄድ ላይ ያለ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"ማሳወቂያዎች"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ክፈት"</string>
<string name="phone_label" msgid="2320074140205331708">"ስልክ ክፈት"</string>
<string name="camera_label" msgid="7261107956054836961">"ካሜራ ክፈት"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"የተንቀሳቃሽ ስልክ መገናኛ ነጥብ በርቷል።"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"ማያ ገጽ መውሰድ ቆሟል።"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ብሩህነት ያሳዩ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2ጂ-3ጂ ውሂብ ጠፍቷል"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4ጂ ውሂብ ጠፍቷል"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ውሂብ ጠፍቷል"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"መሳሪያዎ እርስዎ ያዘጋጁት ገደብ ላይ ስለደረሰ ውሂብን አጥፍቷል።\n\nመልሰው ማብራት ከአገልግሎት አቅራቢዎ ክፍያዎችን ሊያስከትል ይችላል።"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ውሂብ ያብሩ"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2ጂ-3ጂ ውሂብ ላፍታ ቆሟል"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4ጂ ውሂብ ላፍታ ቆሟል"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"የተንቀሳቃሽ ስልክ ውሂብ ላፍታ ቆሟል"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ውሂብ ላፍታ ቆሟል"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"የእርስዎ የተዋቀረው የውሂብ ገደብ ላይ ስለተደረሰ፣ የዚህን ዑደት አጠቃቀም ለማስታወስ መሣሪያው ላፍታ ቆሟል።\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="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ይደበቅ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"በቅንብሮች ውስጥ በሚቀጥለው ጊዜ እንዲበራ በሚያደርጉበት ጊዜ ዳግመኛ ብቅ ይላል።"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ደብቅ"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው መሆን ይፈልጋል።"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ፍቀድ"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ከልክል"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c3cb56b..f933a12 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -25,10 +25,14 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"شاشة واحدة في النظرة عامة"</item>
- <item quantity="other" msgid="5523506463832158203">"%d من الشاشات في النظرة عامة"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="zero"> لا توجد أية شاشات (%d) في النظرة العامة</item>
+ <item quantity="two">شاشتان (%d) في النظرة العامة</item>
+ <item quantity="few">%d شاشات في النظرة العامة</item>
+ <item quantity="many">%d شاشة في النظرة العامة</item>
+ <item quantity="other">%d من الشاشات في النظرة العامة</item>
+ <item quantity="one">شاشة واحدة في النظرة العامة</item>
+ </plurals>
<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>
@@ -88,7 +92,6 @@
<string name="unlock_label" msgid="8779712358041029439">"إلغاء القفل"</string>
<string name="phone_label" msgid="2320074140205331708">"فتح الهاتف"</string>
<string name="camera_label" msgid="7261107956054836961">"فتح الكاميرا"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</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>
@@ -143,7 +146,7 @@
<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_no_sim" msgid="8274017118472455155">"ليست هناك بطاقة SIM."</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"ليست هناك شريحة SIM."</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ربط البلوتوث."</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"وضع الطائرة."</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"مستوى البطارية <xliff:g id="NUMBER">%d</xliff:g> في المائة."</string>
@@ -201,12 +204,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"تم تشغيل نقطة اتصال الجوّال."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"توقف إرسال الشاشة."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"سطوع الشاشة"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2-3 غيغابايت من البيانات المعطلة"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4 غيغابايت من البيانات المعطلة"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"البيانات الخلوية معطلة"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"البيانات معطلة"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"عطل جهازك البيانات نظرًا لبلوغها الحد الذي تم تعيينه.\n\nعلمًا بأن إعادتها قد يؤدي إلى تحمل رسوم من قبل مشغّل شبكة الجوّال."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"تشغيل البيانات"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"بيانات شبكات الجيل الثاني والثالث متوقفة مؤقتًا"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"تم إيقاف بيانات شبكة الجيل الرابع مؤقتًا"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"تم إيقاف بيانات شبكة الجوّال مؤقتًا"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"تم إيقاف البيانات مؤقتًا"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"نظرًا لأنك بلغت الحد الأقصى المحدد للبيانات، فقد أوقف الجهاز استخدام البيانات مؤقتًا في بقية هذه الدورة.\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="gps_notification_searching_text" msgid="8574247005642736060">"جارٍ البحث عن GPS"</string>
@@ -369,4 +372,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"هل تريد إخفاء <xliff:g id="TILE_LABEL">%1$s</xliff:g>؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"سيظهر مرة أخرى عند تمكينه في الإعدادات المرة التالية."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"إخفاء"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"يريد <xliff:g id="APP_NAME">%1$s</xliff:g> أن يكون مربع حوار مستوى الصوت."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"سماح"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رفض"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 40946d3..6212b3f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 екран в панела за общ преглед"</item>
- <item quantity="other" msgid="5523506463832158203">"%d екрана в панела за общ преглед"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d екрана в панела за общ преглед</item>
+ <item quantity="one">1 екран в панела за общ преглед</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"отключване"</string>
<string name="phone_label" msgid="2320074140205331708">"отваряне на телефона"</string>
<string name="camera_label" msgid="7261107956054836961">"отваряне на камерата"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Бутон за превключване на метода на въвеждане."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобилната точка за достъп се включи."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Предаването на съдържанието от екрана спря."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Яркост на екрана"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Данните от 2G – 3G са изключени"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Данните от 4G са изключени"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобилните данни са изключени"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Данните са изключени"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Устройството ви изключи данните, защото зададеното от вас ограничение бе достигнато.\n\nПовторното им включване може да доведе до таксуване от оператора ви."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Включване на данните"</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="4651001290947318931">"Мобилните данни са поставени на пауза"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Данните са поставени на пауза"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Тъй като зададеното от вас ограничение за данни бе достигнато, устройството постави преноса им на пауза за остатъка от този цикъл.\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="gps_notification_searching_text" msgid="8574247005642736060">"Търси се GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Да се скрие ли „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Бързите настройки ще се покажат отново следващия път, когато ги включите от „Настройки“."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Скриване"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска да изпълнява ролята на диалоговия прозорец за силата на звука."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Разрешаване"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Отказване"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index f02a278..a6fc71f 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"এক নজরে-এ ১টি স্ক্রীন"</item>
- <item quantity="other" msgid="5523506463832158203">"এক নজরে-এ %dটি স্ক্রীন"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"চলতে-থাকা"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"আনলক করুন"</string>
<string name="phone_label" msgid="2320074140205331708">"ফোন খুলুন"</string>
<string name="camera_label" msgid="7261107956054836961">"ক্যামেরা খুলুন"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ইনপুট পদ্ধতির বোতাম পরিবর্তন করুন৷"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"মোবাইল হটস্পট চালু হয়েছে।"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"স্ক্রীন কাস্ট করা থেমেছে।"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"প্রদর্শনের উজ্জ্বলতা"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ডেটা বন্ধ"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ডেটা বন্ধ"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"সেলুলার ডেটা বন্ধ"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ডেটা বন্ধ"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"আপনার সেট করা ডেটা সীমায় পৌঁছে যাওয়ায় আপনার ডিভাইসটি ডেটা বন্ধ করে দিয়েছে।\n\nএটি চালু করে দিলে আপনাকে পরিষেবা প্রদানকারীর করা চার্জ বহন করতে হতে পারে।"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ডেটা চালু করুন"</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="4651001290947318931">"সেলুলার ডেটা বিরতি দেওয়া হয়েছে"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ডেট বিরতি দেওয়া হয়েছে"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"আপনার সেট ডেটার সীমা অবধি পৌঁছনোর কারনে ডিভাইস এই চক্রের অবশিষ্টাংশের জন্য ডেটা ব্যবহারে বিরতি দেওয়া হয়েছে৷ \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="gps_notification_searching_text" msgid="8574247005642736060">"GPS এর জন্য অনুসন্ধান করা হচ্ছে"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> লুকাবেন?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"আপনি পরের বার সেটিংস-এ এটি চালু করলে এটি উপস্থিত হবে"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"লুকান"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ভলিউম ডায়লগ হতে চায়৷"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"মঞ্জুরি দিন"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"প্রত্যাখ্যান করুন"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index c9d7f3e..d48be7e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informació de l\'aplicació"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Aquí es mostren les teves pantalles recents."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Omet les aplicacions recents"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 pantalla a Visió general"</item>
- <item quantity="other" msgid="5523506463832158203">"%d pantalles a Visió general"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d pantalles en la visió general</item>
+ <item quantity="one">1 pantalla en la visió general</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Cap notificació"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloqueja"</string>
<string name="phone_label" msgid="2320074140205331708">"obre el telèfon"</string>
<string name="camera_label" msgid="7261107956054836961">"obre la càmera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botó de zoom de compatibilitat."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Amplia menys com més gran sigui la pantalla."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connectat."</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"El punt d\'accés mòbil està activat."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"S\'ha aturat l\'emissió de la pantalla."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brillantor de la pantalla"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"L\'ús de dades 2G-3G està desactivat"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"L\'ús de dades 4G està desactivat"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Les dades mòbils estan desactivades"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Les dades estan desactivades"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"S\'han desactivat les dades del dispositiu perquè ha arribat al límit que has definit.\n\nSi les tornes a activar, l\'operador de telefonia mòbil et pot aplicar càrrecs."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activa les dades"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Les dades 2G-3G estan aturades"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Les dades 4G estan aturades"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Les dades mòbils estan aturades"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Les dades estan aturades"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Com que has arribat al límit de dades establert, s\'ha aturat l\'ús de dades del dispositiu per a la resta d\'aquest cicle.\n\nSi el reprens, l\'operador de telefonia mòbil pot aplicar càrrecs."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reprèn"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No hi ha connexió a Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: connectada"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"S\'està cercant un GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vols amagar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tornarà a mostrar-se la propera vegada que l\'activis a la configuració."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Amaga"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vol passar a ser el diàleg del volum."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permet"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denega"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 5f48a85..8c7428b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -25,10 +25,12 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informace o aplikaci"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Zde budou zobrazeny vaše poslední obrazovky"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Zavřít nové aplikace"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 obrazovka v Přehledu"</item>
- <item quantity="other" msgid="5523506463832158203">"Počet obrazovek v Přehledu: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="few">%d obrazovky v Přehledu</item>
+ <item quantity="many">%d obrazovky v Přehledu</item>
+ <item quantity="other">%d obrazovek v Přehledu</item>
+ <item quantity="one">1 obrazovka v Přehledu</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žádná oznámení"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"odemknout"</string>
<string name="phone_label" msgid="2320074140205331708">"otevřít telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"spustit fotoaparát"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačítko úpravy velikosti z důvodu kompatibility"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zvětšit menší obrázek na větší obrazovku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Rozhraní Bluetooth je připojeno."</string>
@@ -203,12 +204,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobile hotspot je zapnutý."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Odesílání obrazovky zastaveno."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeje"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G a 3G jsou vypnuta"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G jsou vypnuta"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilní data jsou vypnuta"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data jsou vypnuta"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Zařízení datové přenosy vypnulo, protože dosáhlo limitu, který jste nastavili.\n\nJejich opětovné zapnutí může vézt k účtování poplatků operátorem."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Zapnout data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G a 3G jsou pozastavena"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilní data jsou pozastavena"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data jsou pozastavena"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Protože jste dosáhli nastaveného limitu dat, zařízení využití dat pro zbytek tohoto cyklu pozastavilo.\n\nObnovení může vést k poplatkům od operátora."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Pokračovat"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Žádné přip. k internetu"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: připojeno"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhledávání satelitů GPS"</string>
@@ -371,4 +372,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skrýt <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tato položka se znovu zobrazí, až ji v nastavení znovu zapnete."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skrýt"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce být dialogem hlasitosti."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Povolit"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmítnout"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 0beb8fb..ff21bc9 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Oplysninger om appen"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Dine seneste skærme vises her"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Luk de seneste apps"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Ét skærmbillede i Oversigt"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skærmbilleder i Oversigt"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d skærmbilleder i Oversigt</item>
+ <item quantity="other">%d skærmbilleder i Oversigt</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen underretninger"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"lås op"</string>
<string name="phone_label" msgid="2320074140205331708">"åbn telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"åbn kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knap for kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom mindre til større skærm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tilsluttet."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilhotspot er slået til."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Casting af din skærm er stoppet."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Skærmens lysstyrke"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G-data er deaktiveret"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-data er deaktiveret"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobildata er deaktiveret"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data er deaktiveret"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Enheden har deaktiveret data, fordi den grænse, du har angivet, er nået.\n\nHvis du aktiverer dataforbrug igen, kan mobilselskabet pålægge gebyrer."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Aktivér data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data er sat på pause"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er sat på pause"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata er sat på pause"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data er sat på pause"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Eftersom din fastsatte datagrænse blev nået, har enheden sat dataforbruget på pause i den resterende del af cyklussen.\n\nHvis du genaktiverer dataforbruget, kan det medføre gebyrer fra dit mobilselskab."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Genoptag"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen internetforb."</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi er forbundet"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igen, næste gang du aktiverer den i indstillingerne."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ønsker at være dialogboksen for lydstyrke."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillad"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afvis"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index b408937..a5685ee 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"App-Info"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Hier sehen Sie Ihre zuletzt geöffneten Apps."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Kürzlich geöffnete Apps schließen"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 Bildschirm in der Übersicht"</item>
- <item quantity="other" msgid="5523506463832158203">"%d Bildschirme in der Übersicht"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d Bildschirme in der Übersicht</item>
+ <item quantity="one">1 Bildschirm in der Übersicht</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"Entsperren"</string>
<string name="phone_label" msgid="2320074140205331708">"Telefon öffnen"</string>
<string name="camera_label" msgid="7261107956054836961">"Kamera öffnen"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Schaltfläche für Kompatibilitätszoom"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom auf einen größeren Bildschirm"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Mit Bluetooth verbunden"</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Der mobile Hotspot ist aktiviert."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Die Bildschirmübertragung wurde angehalten."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Helligkeit des Displays"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G/3G-Daten deaktiviert"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-Daten deaktiviert"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilfunkdaten deaktiviert"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Daten deaktiviert"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Die Datennutzung wurde auf Ihrem Gerät deaktiviert, da das von Ihnen festgelegte Limit erreicht wurde.\n\nWenn Sie die Funktion erneut aktivieren, berechnet Ihr Mobilfunkanbieter möglicherweise Gebühren."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Daten aktivieren"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-/3G-Daten pausiert"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-Daten pausiert"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilfunkdaten pausiert"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Daten pausiert"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Da Ihr festgelegtes Datenlimit erreicht wurde, hat das Gerät die Datennutzung für den Rest dieses Zeitraums pausiert.\n\nWenn Sie diese fortsetzen, können möglicherweise Kosten bei Ihrem Mobilfunkanbieter entstehen."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Fortsetzen"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Keine Internetverbindung"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN verbunden"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht..."</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ausblenden?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Sie wird wieder eingeblendet, wenn Sie sie in den Einstellungen erneut aktivieren."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ausblenden"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> will die Lautstärke regeln."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Zulassen"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ablehnen"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 97a175a..ec61344 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 οθόνη στην Επισκόπηση"</item>
- <item quantity="other" msgid="5523506463832158203">"%d οθόνες στην Επισκόπηση"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d οθόνες στην Επισκόπηση</item>
+ <item quantity="one">1 οθόνη στην Επισκόπηση</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ξεκλείδωμα"</string>
<string name="phone_label" msgid="2320074140205331708">"άνοιγμα τηλεφώνου"</string>
<string name="camera_label" msgid="7261107956054836961">"άνοιγμα φωτογραφικής μηχανής"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Το σημείο πρόσβασης κινητής συσκευής ενεργοποιήθηκε."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Η μετάδοση της οθόνης διακόπηκε."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Τα δεδομένα 2G-3G είναι ανενεργά"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Τα δεδομένα 4G είναι ανενεργά"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Τα δεδομένα κινητής τηλεφωνίας είναι ανενεργά"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Τα δεδομένα είναι ανενεργά"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Τα δεδομένα απενεργοποιήθηκαν στη συσκευή σας, επειδή εξαντλήσατε το όριο που ορίσατε.\n\nΗ επανενεργοποίησή τους ενδέχεται να επιφέρει χρεώσεις από την εταιρεία κινητής τηλεφωνίας σας."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ενεργοποίηση δεδομένων"</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="4651001290947318931">"Τα δεδομένα κινητής τηλεφωνίας τέθηκαν σε παύση"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Τα δεδομένα τέθηκαν σε παύση"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Επειδή συμπληρώθηκε το όριο των δεδομένων που ορίστηκε για τη συσκευή σας, η χρήση δεδομένων τέθηκε σε παύση για το υπόλοιπο αυτού του κύκλου.\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="gps_notification_searching_text" msgid="8574247005642736060">"Αναζήτηση για GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Απόκρυψη <xliff:g id="TILE_LABEL">%1$s</xliff:g>;"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Θα εμφανιστεί ξανά την επόμενη φορά που θα το ενεργοποιήσετε στις ρυθμίσεις."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Απόκρυψη"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> θέλει να γίνει το παράθυρο διαλόγου ελέγχου έντασης"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Να επιτραπεί"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 62b93b6..c6cc776 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"App info"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Your recent screens appear here"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Dismiss recent apps"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 screen in Overview"</item>
- <item quantity="other" msgid="5523506463832158203">"%d screens in Overview"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d screens in Overview</item>
+ <item quantity="one">1 screen in Overview</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
<string name="phone_label" msgid="2320074140205331708">"open phone"</string>
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobile hotspot turned on."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Screen casting stopped."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G data is off"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G data is off"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobile data is off"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data is off"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Your device turned off data because it reached the limit you set.\n\nTurning it back on may lead to charges from your operator."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Turn on data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobile data is paused"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is paused"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your operator."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Resume"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Searching for GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"It will reappear the next time you turn it on in settings."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Hide"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wants to be the volume dialogue."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Allow"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 62b93b6..c6cc776 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"App info"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Your recent screens appear here"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Dismiss recent apps"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 screen in Overview"</item>
- <item quantity="other" msgid="5523506463832158203">"%d screens in Overview"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d screens in Overview</item>
+ <item quantity="one">1 screen in Overview</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"unlock"</string>
<string name="phone_label" msgid="2320074140205331708">"open phone"</string>
<string name="camera_label" msgid="7261107956054836961">"open camera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobile hotspot turned on."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Screen casting stopped."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G data is off"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G data is off"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobile data is off"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data is off"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Your device turned off data because it reached the limit you set.\n\nTurning it back on may lead to charges from your operator."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Turn on data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobile data is paused"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data is paused"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your operator."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Resume"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Searching for GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"It will reappear the next time you turn it on in settings."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Hide"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wants to be the volume dialogue."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Allow"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index f79c5ed..a04779b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Información de la aplicación"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Las pantallas recientes aparecen aquí."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Rechazar aplicaciones recientes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 pantalla en Recientes"</item>
- <item quantity="other" msgid="5523506463832158203">"%d pantallas en Recientes"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d pantallas en Recientes</item>
+ <item quantity="one">1 pantalla en Recientes</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
<string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Zona móvil activada"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Transmisión de pantalla detenida"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Datos 2G-3G desactivados"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Datos 4G desactivados"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Datos móviles desactivados"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Datos desactivados"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"El dispositivo desactivó los datos porque alcanzó el límite establecido.\n\nSi los vuelves a activar, podrían aplicarse cargos del proveedor."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activar datos"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Datos móviles pausados"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datos pausados"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Debido que se alcanzó el límite de datos establecido, el dispositivo pausó el uso de datos para el resto de este ciclo.\n\nLa reanudación podría tener como resultado cargos del proveedor."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reanudar"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sin conexión a Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá a aparecer la próxima vez que se active en la configuración."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quiere ser el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 6bd03c90..a9103a8 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Información de la aplicación"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Aquí aparecerán tus pantallas recientes"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicaciones recientes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 pantalla en Visión general"</item>
- <item quantity="other" msgid="5523506463832158203">"%d pantallas en Visión general"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d pantallas en Visión general</item>
+ <item quantity="one">1 pantalla en Visión general</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
<string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidad"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de pantalla más pequeña a más grande"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Punto de acceso móvil activado."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Envío de pantalla detenido."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de la pantalla"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Datos 2G-3G desactivados"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Datos 4G desactivados"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Datos móviles desactivados"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Conexión de datos desactivada"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Se ha desactivado la conexión de datos del dispositivo porque se ha alcanzado el límite establecido.\n\nSi se vuelve a activar, se podrían aplicar cargos del operador."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activar conexión de datos"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Datos móviles pausados"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datos pausados"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Has alcanzado el límite de datos establecido, por lo que el dispositivo ha pausado el uso de datos para el resto de este ciclo.\n\nSi lo reanudas, el operador puede facturar cargos."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reanudar"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sin conexión a Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Con conexión Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá a aparecer la próxima vez que actives esta opción en Ajustes."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quiere ser el cuadro de diálogo de volumen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b17eb05..4f891e3 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Rakenduse teave"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Teie viimane ekraanikuva ilmub siia"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Loobu hiljutistest rakendustest"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ekraan jaotises Ülevaade"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ekraanikuva jaotises Ülevaade"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d ekraani jaotises Ülevaade</item>
+ <item quantity="one">1 ekraan jaotises Ülevaade</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Teatisi pole"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Jätkuv"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Märguanded"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ava lukk"</string>
<string name="phone_label" msgid="2320074140205331708">"ava telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"ava kaamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Sobivussuumi nupp."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Suumi suuremale ekraanile vähem."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth on ühendatud."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiilside leviala on sisse lülitatud."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ekraanikuva ülekandmine on peatatud."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekraani heledus"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G andmeside on väljalülitatud"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G andmeside on väljalülitatud"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mob. andmeside väljalülitatud"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Andmeside on väljalülitatud"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Seade lülitas andmeside välja, sest teie määratud limiit on täis.\n\nKui lülitate andmeside uuesti sisse, siis võivad lisanduda operaatori tasud."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Lülita andmeside sisse"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G andmekasutus on peatatud"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G andmekasutus on peatatud"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiilse andmeside kasutus on peatatud"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Andmekasutus on peatatud"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kuna jõudsite andmemahu määratud piirini, peatas seade andmekasutuse ülejäänud tsükliks.\n\nJätkamisel võivad lisanduda operaatoritasud."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jätka"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Interneti-ühendus puudub"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WiFi on ühendatud"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-i otsimine"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Kas peita <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"See kuvatakse uuesti järgmisel korral, kui selle seadetes sisse lülitate."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Peida"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> tahab olla helitugevuse dialoog."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Luba"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Keela"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index be21e9d..3697b05 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Aplikazioaren informazioa"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Ikusitako azken pantailak erakusten dira hemen"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Baztertu azken aplikazioak"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Pantaila bat dago ikuspegi orokorrean"</item>
- <item quantity="other" msgid="5523506463832158203">"%d pantaila daude ikuspegi orokorrean"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d pantaila daude ikuspegi orokorrean</item>
+ <item quantity="one">Pantaila bat dago ikuspegi orokorrean</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ez dago jakinarazpenik"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Abian"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Jakinarazpenak"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desblokeatu"</string>
<string name="phone_label" msgid="2320074140205331708">"ireki telefonoan"</string>
<string name="camera_label" msgid="7261107956054836961">"ireki kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Idazketa-metodoa aldatzeko botoia."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoom-bateragarritasunaren botoia."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Handiagotu pantaila txikia."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetootha konektatuta."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Konexioa partekatzeko aukera aktibatu egin da."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Pantaila igortzeari utzi zaio."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Bistaratu distira"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G datu-konexioa desaktibatuta dago"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G datu-konexioa desaktibatuta dago"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Datu mugikorrak desaktibatuta daude"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Datu-konexioa desaktibatuta dago"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Gailuak datu-konexioa desaktibatu du, ezarritako mugara iritsi delako.\n\nBerriro aktibatuz gero, operadoreak zerbait kobratuko dizu agian."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Aktibatu datu-konexioa"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G datuen erabilera eten da"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datuen erabilera eten da"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Sare mugikorreko datuen erabilera eten da"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datuen erabilera eten da"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Zehaztuta duzun datuen erabilera-mugara iritsi zarenez, gailuak datuen erabilera eten du zikloa amaitzen den arte.\n\nDatuak erabiltzen jarraitzen baduzu, gastu gehiago ordaindu beharko dizkiozu agian operadoreari."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jarraitu erabiltzen"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ez duzu Interneteko konexiorik"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi konektatuta"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS seinalearen bila"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ezkutatu nahi duzu?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ezarpenetan aktibatzen duzun hurrengoan agertuko da berriro."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ezkutatu"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> bolumenaren leihoa izan nahian ari da."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Baimendu"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ukatu"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 11021b1..602d1c2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"۱ صفحه در نمای کلی"</item>
- <item quantity="other" msgid="5523506463832158203">"%d صفحه در نمای کلی"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلانها"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"بازکردن قفل"</string>
<string name="phone_label" msgid="2320074140205331708">"باز کردن تلفن"</string>
<string name="camera_label" msgid="7261107956054836961">"باز کردن دوربین"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"نقطه اتصال دستگاه همراه روشن شد."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"فرستادن صفحه نمایش متوقف شد."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"روشنایی نمایشگر"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"داده 2G-3G خاموش است"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"داده 4G خاموش است"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"داده شبکه سلولی خاموش است"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"داده خاموش است"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"دستگاه شما خاموش شد زیرا به حد تنظیم شده توسط شما رسید.\n\nروشن کردن مجدد آن میتواند به هزینههایی از طرف شرکت مخابراتی شما منجر شود."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"روشن کردن داده"</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="4651001290947318931">"داده شبکه همراه موقتاً متوقف شده است"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"داده موقتاً متوقف شده است"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"چون به محدودیت داده تنظیم شده رسیدهاید، دستگاه مصرف داده را برای باقیمانده این دوره موقتاً متوقف کرده است.\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="gps_notification_searching_text" msgid="8574247005642736060">"جستجو برای GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"دفعه بعد که آن را روشن کنید، در تنظیمات نشان داده میشود."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"پنهان کردن"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> میخواهد کنترلکننده صدا باشد."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"مجاز"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"رد کردن"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترلکننده اصلی، لمس کنید."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index eac124e..4224e30 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Sovelluksen tiedot"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Äskettäin käytetyt ruudut näkyvät tässä"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Hylkää viimeaikaiset sovellukset"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 näyttö Viimeisimmät-kohdassa"</item>
- <item quantity="other" msgid="5523506463832158203">"%d näyttöä Viimeisimmät-kohdassa"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d näyttöä Yleistä-kohdassa</item>
+ <item quantity="one">1 näyttö Yleistä-kohdassa</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ei ilmoituksia"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"avaa lukitus"</string>
<string name="phone_label" msgid="2320074140205331708">"avaa puhelin"</string>
<string name="camera_label" msgid="7261107956054836961">"avaa kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Yhteensopivuuszoomaus-painike."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoomaa pienemmältä suuremmalle ruudulle."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth yhdistetty."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiiliyhteyden hotspot otettiin käyttöön."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ruudun lähetys pysäytettiin."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Näytön kirkkaus"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G-tiedonsiirto ei ole käytössä"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-tiedonsiirto ei ole käytössä"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobiilitiedonsiirto ei ole käytössä"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Tiedonsiirto ei ole käytössä"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Laitteesi poisti tiedonsiirron käytöstä, koska se saavutti asettamasi rajan.\n\nOperaattorisi saattaa veloittaa sinulta lisämaksuja, jos otat sen uudelleen käyttöön."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ota tiedonsiirto käyttöön"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G-tiedonsiirto keskeytettiin"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-tiedonsiirto keskeytettiin"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiilitiedonsiirto keskeytettiin"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Tiedonsiirto keskeytettiin"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Määrittämäsi tiedonsiirtorajoitus saavutettiin, ja laite keskeytti tiedonsiirron tämän kauden loppuajaksi.\n\nOperaattorisi voi veloittaa sinulta lisämaksun, jos jatkat tiedonsiirtoa."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Jatka"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ei internetyhteyttä"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi yhdistetty"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Piilotetaanko <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Se tulee takaisin näkyviin, kun seuraavan kerran otat sen käyttöön asetuksissa."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Piilota"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> haluaa olla äänenvoimakkuusvalinta."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Salli"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Estä"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 387b621..b064d0e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informations sur l\'application"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Vos écrans récents s\'affichent ici"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Masquer les applications récentes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 écran dans Aperçu"</item>
- <item quantity="other" msgid="5523506463832158203">"%d écrans dans Aperçu"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">Aperçu de %d écran</item>
+ <item quantity="other">Aperçu de %d écrans</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"déverrouiller"</string>
<string name="phone_label" msgid="2320074140205331708">"Ouvrir le téléphone"</string>
<string name="camera_label" msgid="7261107956054836961">"Ouvrir l\'appareil photo"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Point d\'accès mobile activé."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Diffusion d\'écran arrêtée."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'écran"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Données 2G/3G désactivées"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Données 4G désactivées"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Données cellulaire désactivées"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Données désactivées"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Votre appareil a désactivé les données, car il a atteint la limite définie.\n\nSi vous les réactivez, votre fournisseur de services risque de vous facturer des frais supplémentaires."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activer les données"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G/3G désactivées"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Données cellulaires désactivées"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Données désactivées"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vous avez atteint le quota de données maximal. La consommation des données a donc été interrompue pour la fin de la période de facturation en cours.\n\nSi vous réactivez les données, votre fournisseur de services risque de vous facturer des frais supplémentaires."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reprendre"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Masquer"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> souhaite être la boîte de dialogue du volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Autoriser"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index eda4afb..5af507b 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informations sur l\'application"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Vos écrans récents s\'affichent ici"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Masquer les applications récentes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 écran dans Aperçu"</item>
- <item quantity="other" msgid="5523506463832158203">"%d écrans dans Aperçu"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d écran dans Aperçu</item>
+ <item quantity="other">%d écrans dans Aperçu</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"déverrouiller"</string>
<string name="phone_label" msgid="2320074140205331708">"ouvrir le téléphone"</string>
<string name="camera_label" msgid="7261107956054836961">"ouvrir l\'appareil photo"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Point d\'accès mobile activé."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Diffusion d\'écran interrompue."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'affichage"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Données 2G-3G désactivées"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Données 4G désactivées"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Données mobiles désactivées"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Données désactivées"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Votre appareil a désactivé les données, car il a atteint la limite que vous avez définie.\n\nSi vous les réactivez, votre opérateur risque de vous facturer des frais supplémentaires."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activer les données"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G-3G désactivées"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Données mobiles désactivées"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Données désactivées"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vous avez atteint le quota de données maximal. La consommation des données a donc été interrompue pour la fin de la période de facturation en cours.\n\nSi vous réactivez les données, votre opérateur risque de vous facturer des frais supplémentaires."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Réactiver"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g> ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Cet élément réapparaîtra la prochaine fois que vous l\'activerez dans les paramètres."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Masquer"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> souhaite être la boîte de dialogue du volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Autoriser"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 9ae9493..9b3d62e 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Información da aplicación"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"As túas pantallas recentes aparecen aquí"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Rexeitar aplicacións recentes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 pantalla en Visión xeral"</item>
- <item quantity="other" msgid="5523506463832158203">"%d pantallas en Visión xeral"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d pantallas en visión xeral</item>
+ <item quantity="one">Unha pantalla en visión xeral</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Non hai notificacións"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En curso"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacións"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
<string name="phone_label" msgid="2320074140205331708">"abrir teléfono"</string>
<string name="camera_label" msgid="7261107956054836961">"abrir cámara"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Cambiar o botón do método de entrada."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botón de zoom de compatibilidade"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilidade co tamaño da pantalla."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado"</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Activouse a zona interactiva móbil."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Detívose a emisión en pantalla."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Os datos 2G-3G están desactivados"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Os datos 4G están desactivados"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Os datos móbiles están desactivados"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Os datos están desactivados"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"O teu dispositivo desactivou os datos porque alcanzou o límite establecido.\n\nActivalos de novo pode supoñer gastos adicionais do teu operador."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activar datos"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os datos 2G-3G están en pausa"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os datos 4G están en pausa"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Os datos de móbiles están en pausa"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Os datos están en pausa"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Como acadaches o límite de datos definido, o dispositivo puxo en pausa o uso de datos para o resto do ciclo.\n\nSe retomas o uso, poden aplicarse cargos do operador."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sen Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectada"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Queres ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Volverá aparecer a próxima vez que se active na configuración."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> quere ser o cadro de diálogo de volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denegar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 82f9ddd..65ee915 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"अवलोकन मेें 1 स्क्रीन"</item>
- <item quantity="other" msgid="5523506463832158203">"अवलोकन में %d स्क्रीन"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"अनलॉक करें"</string>
<string name="phone_label" msgid="2320074140205331708">"फ़ोन खोलें"</string>
<string name="camera_label" msgid="7261107956054836961">"कैमरा खोलें"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति बटन स्विच करें."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"मोबाइल हॉटस्पॉट को चालू किया गया."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"स्क्रीन कास्ट करना रुक गया."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"स्क्रीन की स्क्रीन की रोशनी"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G डेटा बंद है"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G डेटा बंद है"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"सेल्युलर डेटा बंद है"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"डेटा बंद है"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"आपके डिवाइस ने डेटा बंद कर दिया है क्योंकि आपके द्वारा सेट की गई सीमा पार हो गई है.\n\nइसे फिर से चालू करने से आपका वाहक शुल्क ले सकता है."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"डेटा चालू करें"</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="4651001290947318931">"सेल्युलर डेटा रोक दिया गया है"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटा रोक दिया गया है"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"चूंकि आपके निर्धारित डेटा की सीमा, सीमा पर पहुंच गई थी, इसलिए डिवाइस ने इस चक्र के रिमाइंडर के लिए डेटा उपयोग को रोक दिया है.\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">"वाई-फ़ाई कनेक्ट किया गया"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS को खोजा जा रहा है"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> को छिपाएं?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"जब आप उसे अगली बार सेटिंग में चालू करेंगे तो वह फिर से दिखाई देगी."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"छिपाएं"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद होना चाहता है."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमति दें"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार करें"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल वॉल्यूम को फिर से लाने के लिए स्पर्श करें."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1a06261..113a0cf 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -25,10 +25,11 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informacije o aplikaciji"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Ovdje se pojavljuju vaši nedavni zasloni"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Odbaci nedavne aplikacije"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 zaslon u Pregledu"</item>
- <item quantity="other" msgid="5523506463832158203">"Broj zaslona u Pregledu: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d zaslon u Pregledu</item>
+ <item quantity="few">%d zaslona u Pregledu</item>
+ <item quantity="other">%d zaslona u Pregledu</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bez obavijesti"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
@@ -88,7 +89,6 @@
<string name="unlock_label" msgid="8779712358041029439">"otključavanje"</string>
<string name="phone_label" msgid="2320074140205331708">"otvaranje telefona"</string>
<string name="camera_label" msgid="7261107956054836961">"otvaranje fotoaparata"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb za kompatibilnost zumiranja."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zumiranje manjeg zaslona na veći."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth povezan."</string>
@@ -201,12 +201,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilna žarišna točka uključena."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Emitiranje zaslona zaustavljeno."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Svjetlina zaslona"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G podaci isključeni"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G podaci isključeni"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilni podaci isključeni"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Podaci su isključeni"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Uređaj je isključio podatke jer je dosegnuo ograničenje koje ste postavili.\n\nAko ih ponovno uključite, mogući su dodatni troškovi za mobilne usluge."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Uključi podatke"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G – 3G podaci pauzirani"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci pauzirani"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci pauzirani"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Podaci su pauzirani"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Budući da je dosegnuto postavljeno ograničenje podataka, uređaj je pauzirao upotrebu podataka za preostali dio ovog ciklusa.\n\nMobilni operater može naplatiti daljnju upotrebu."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nema internetske veze"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS-a"</string>
@@ -369,4 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti pločicu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ponovo će se pojaviti kada je sljedeći put uključite u postavkama."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sakrij"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> želi biti dijaloški okvir za upravljanje glasnoćom."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Dopusti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odbij"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index bc08adc..bdad948 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Alkalmazásinformáció"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"A legutóbbi képernyők itt jelennek meg"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Újabb alkalmazások elvetése"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 képernyő Áttekintés alatt"</item>
- <item quantity="other" msgid="5523506463832158203">"%d képernyő Áttekintés alatt"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d képernyő áttekintés alatt</item>
+ <item quantity="one">1 képernyő áttekintés alatt</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nincs értesítés"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"feloldás"</string>
<string name="phone_label" msgid="2320074140205331708">"telefon megnyitása"</string>
<string name="camera_label" msgid="7261107956054836961">"kamera megnyitása"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kompatibilitási zoom gomb."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kicsinyítsen a nagyobb képernyőhöz."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth csatlakoztatva."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"A mobil hotspot bekapcsolva."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"A képernyő átküldése leállítva."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"A kijelző fényereje"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"A 2G-s és 3G-s adatkapcsolat nem használható"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"A 4G-s adatkapcsolat nem használható"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"A mobiladat-kapcsolat nem használható"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Az adatkapcsolat ki van kapcsolva"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Eszköze leállította az adatkapcsolatot, mert Ön elérte a beállított adatkorlátot.\n\nAz adatkapcsolat újbóli bekapcsolása után szolgáltatója többletköltséget számíthat fel."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Adatkapcsolat engedélyezése"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"A 2G és 3G adatforgalom szünetel."</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"A 4G adatforgalom szünetel"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"A mobilhálózati adatforgalom szünetel"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Az adatforgalom szünetel"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Mivel elérte a beállított adatkorlátot, az eszköz a ciklus fennmaradó részére felfüggesztette az adathasználatot.\n\nHa mégis használja az adatkapcsolatot, akkor szolgáltatója többletköltséget számíthat fel."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Folytatás"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nincs internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi csatlakoztatva"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS keresése"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Elrejti ezt: <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Újból megjelenik majd, amikor ismét engedélyezi a beállítások között."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Elrejtés"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás szeretné kezelni a hangerőt."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Engedélyezés"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Elutasítás"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 9b673bc..6cc1292 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"Համատեսքում ցուցադրված է 1 էկրան:"</item>
- <item quantity="other" msgid="5523506463832158203">"Համատեսքում ցուցադրված է %d էկրան"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"Ընթացիկ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ծանուցումներ"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ապակողպել"</string>
<string name="phone_label" msgid="2320074140205331708">"բացել հեռախոսը"</string>
<string name="camera_label" msgid="7261107956054836961">"բացել ֆոտոխցիկը"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Շարժական կապի WiFi ցրիչը միացավ:"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Էկրանի հեռարձակումն ընդհատվեց:"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ցուցադրել պայծառությունը"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G տվյալների կապն անջատված է"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G տվյալների կապն անջատված է"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Բջջային տվյալներն անջատված են"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Տվյալների կապն անջատված է"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Տվյալների կապը ձեր սարքում անջատվեց, քանի որ դուք հատել եք նշված սահմանաչափը:\n\nԱյն հետ միացնելուց հետո հնարավոր են հավելյալ վճարներ ձեր օպերատորից:"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Միացնել տվյալների կապը"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2Գ-3Գ տվյալների օգտագործումը դադարեցված է"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Գ տվյալների օգտագործումը դադարեցված է"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Բջջային տվյալների օգտագործումը դադարեցված է"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Տվյալների օգտագործումը դադարեցված է"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Քանի որ ձեր սահմանված տվյալների սահմանաչափը սպառվել է, սարքն այլևս չի օգտագործի տվյալները այս ցիկլի մնացած ընթացքում:\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="gps_notification_searching_text" msgid="8574247005642736060">"Որոնում է GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Թաքցնե՞լ <xliff:g id="TILE_LABEL">%1$s</xliff:g>-ը:"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Այն դարձյալ կհայտնվի, երբ նորից միացնեք կարգավորումներում:"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Թաքցնել"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ցանկանում է երկխոսության հավելվածը դառնալ:"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Թույլատրել"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Մերժել"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 54f7f46..26cad0c 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Info apl"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Layar terkini Anda muncul di sini"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Tutup aplikasi terbaru"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 layar dalam Ringkasan"</item>
- <item quantity="other" msgid="5523506463832158203">"%d layar dalam Ringkasan"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d layar dalam Ringkasan</item>
+ <item quantity="one">1 layar dalam Ringkasan</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tidak ada pemberitahuan"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
<string name="phone_label" msgid="2320074140205331708">"buka ponsel"</string>
<string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tombol perbesar/perkecil kompatibilitas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Perbesar dari layar kecil ke besar."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tersambung."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Hotspot seluler diaktifkan."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Transmisi layar berhenti."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan tampilan"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G-3G nonaktif"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G nonaktif"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Data seluler nonaktif"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data nonaktif"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Perangkat Anda menonaktifkan data karena data mencapai batas yang Anda setel.\n\nMengaktifkan kembali data dapat membuat Anda terkena biaya dari operator."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Aktifkan data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data seluler dijeda"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data dijeda"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Karena batas data yang disetel telah tercapai, perangkat telah menjeda penggunaan data selama sisa waktu siklus ini.\n\nMelanjutkan dapat mengakibatkan tagihan dari operator."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Lanjutkan"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Tidak ada sambungan internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tersambung"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ini akan muncul kembali saat Anda mengaktifkannya dalam setelan."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sembunyikan"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ingin menjadi dialog volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Izinkan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 8fcf8b1..c7afebc 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Upplýsingar um forrit"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Nýlegar skjámyndir birtast hér"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Hunsa nýleg forrit"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Ein skjámynd í yfirliti"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skjámyndir í yfirliti"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d skjámynd í yfirliti</item>
+ <item quantity="other">%d skjámyndir í yfirliti</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Engar tilkynningar"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Áframhaldandi"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Tilkynningar"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"taka úr lás"</string>
<string name="phone_label" msgid="2320074140205331708">"opna síma"</string>
<string name="camera_label" msgid="7261107956054836961">"opna myndavél"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Hnappur til að skipta um innsláttaraðferð."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Hnappur fyrir samhæfisaðdrátt."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aðlaga forrit fyrir lítinn skjá að stærri skjá."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth tengt."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Kveikt á farsímaaðgangsstað."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Skjáútsendingu hætt."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Birtustig skjás"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Slökkt er á 2G- og 3G-gögnum"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Slökkt er á 4G-gögnum"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Slökkt er á farsímagögnum"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Slökkt er á gagnaflutningi"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Slökkt var á gagnaflutningi í tækinu vegna þess að hámarkinu sem þú valdir var náð.\n\nSímafyrirtækið þitt kann að taka gjald ef þú kveikir á honum aftur."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Kveikja á gagnaflutningi"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Slökkt er á 2G- og 3G-gögnum"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Slökkt er á 4G-gögnum"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Slökkt er á farsímagögnum"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Slökkt er á gagnanotkun"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Þar sem gagnahámarkinu var náð hefur tækið slökkt á gagnanotkun það sem eftir er af þessu tímabili.\n\nEf þú heldur áfram kann það að leiða til kostnaðar frá símafyrirtækinu."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Halda áfram"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Engin nettenging"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tengt"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Leitar að GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fela <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Þetta birtist aftur næst þegar þú kveikir á því í stillingunum."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Fela"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vill vera hljóðstyrksvalmyndin."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Leyfa"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Hafna"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0668038..7f5224e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informazioni applicazione"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Le tue schermate recenti vengono visualizzate in questa sezione"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignora app recenti"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 schermata in Panoramica"</item>
- <item quantity="other" msgid="5523506463832158203">"%d schermate in Panoramica"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d schermate in Panoramica</item>
+ <item quantity="one">1 schermata in Panoramica</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"sblocca"</string>
<string name="phone_label" msgid="2320074140205331708">"apri telefono"</string>
<string name="camera_label" msgid="7261107956054836961">"apri fotocamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Pulsante zoom compatibilità."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom inferiore per schermo più grande."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth collegato."</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Hotspot mobile attivato."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Trasmissione dello schermo interrotta."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Luminosità dello schermo"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Dati 2G-3G disattivati"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Dati 4G disattivati"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Rete dati disattivata"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dati disattivati"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Il tuo dispositivo ha disattivato il traffico dati perché hai raggiunto il limite prestabilito.\n\nLa riattivazione potrebbe comportare l\'applicazione di costi aggiuntivi da parte del tuo operatore."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Attiva i dati"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dati 2G-3G sospesi"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dati 4G sospesi"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Dati cellulari sospesi"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dati sospesi"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Hai raggiunto il tuo limite di dati, pertanto sul dispositivo è stato sospeso l\'utilizzo di dati per la parte rimanente del ciclo.\n\nSe riprendi a utilizzare i dati, l\'operatore potrebbe addebitarti costi."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Riprendi"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nessuna connessione"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connesso"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Ricerca del GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Nascondere <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Verranno visualizzate di nuovo quando le riattiverai nelle impostazioni."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Nascondi"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> desidera fungere da finestra di dialogo relativa al volume"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Consenti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Nega"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ac7fd18..5090ca7 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -25,10 +25,12 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"מסך אחד ב\'סקירה\'"</item>
- <item quantity="other" msgid="5523506463832158203">"%d מסכים ב\'סקירה\'"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="two">%d מסכים ב’סקירה‘</item>
+ <item quantity="many">%d מסכים ב’סקירה‘</item>
+ <item quantity="other">%d מסכים ב’סקירה‘</item>
+ <item quantity="one">מסך אחד ב’סקירה‘</item>
+ </plurals>
<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>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"בטל את הנעילה"</string>
<string name="phone_label" msgid="2320074140205331708">"פתח את הטלפון"</string>
<string name="camera_label" msgid="7261107956054836961">"פתח את המצלמה"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</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>
@@ -201,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"נקודה לשיתוף אינטרנט בנייד מופעלת."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"העברת המסך הופסקה."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"בהירות תצוגה"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"נתונים בחיבור 2G-3G כובו"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"נתונים בחיבור 4G כובו"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"נתונים בחיבור סלולרי כובו"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"חיבור הנתונים כובה"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"המכשיר שלך כיבה את חיבור הנתונים מפני שהוא הגיע למגבלה שהגדרת.\n\nהפעלה מחדש עשויה להוביל לחיובים על ידי הספק."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"הפעל חיבור נתונים"</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="4651001290947318931">"השימוש בנתונים סלולריים מושהה"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"השימוש בנתונים מושהה"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"מכיוון שהגעת למגבלת הנתונים שהגדרת, המכשיר השהה את השימוש בנתונים עד סוף התקופה.\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="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
@@ -369,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"להסתיר<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"יופיע מחדש בפעם הבאה שתפעיל את האפשרות בהגדרות."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"הסתר"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> מנסה לפעול בתור תיבת הדו-שיח של עוצמת הקול."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"התר"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"דחה"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 8c30d58..d106f91 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"[最近]に1個の画面があります"</item>
- <item quantity="other" msgid="5523506463832158203">"[最近]に%d個の画面があります"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">[最近]に%d個の画面があります</item>
+ <item quantity="one">[最近]に1個の画面があります</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ロック解除"</string>
<string name="phone_label" msgid="2320074140205331708">"電話を起動"</string>
<string name="camera_label" msgid="7261107956054836961">"カメラを起動"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"モバイルアクセスポイントをONにしました。"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"画面のキャストが停止しました。"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ディスプレイの明るさ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G~3Gデータが無効になりました"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4Gデータが無効になりました"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"モバイルデータが無効になりました"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"データが無効になりました"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"設定された上限に達したため、端末のデータ接続が無効になりました。\n\n有効に戻すと、携帯通信会社から課金される可能性があります。"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"データ接続を有効にする"</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="4651001290947318931">"モバイルデータは一時停止中です"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"データの一時停止"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"設定されたデータの上限に達したため、このサイクルの終了までこの端末でのデータの利用を一時停止しました。\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="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>を非表示にしますか?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"次回、設定でONにすると再表示されます。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"非表示"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>が音量ダイアログとして機能します。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"許可"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"許可しない"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 7262638..cb8c609 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"ნაჩვენებია 1 ეკრანი"</item>
- <item quantity="other" msgid="5523506463832158203">"ნაჩვენებია %d ეკრანი"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d ეკრანი მიმოხილვაში</item>
+ <item quantity="one">1 ეკრანი მიმოხილვაში</item>
+ </plurals>
<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>
@@ -80,7 +80,7 @@
<string name="accessibility_back" msgid="567011538994429120">"უკან"</string>
<string name="accessibility_home" msgid="8217216074895377641">"საწყისი"</string>
<string name="accessibility_menu" msgid="316839303324695949">"მენიუ"</string>
- <string name="accessibility_recent" msgid="5208608566793607626">"გადახედვა"</string>
+ <string name="accessibility_recent" msgid="5208608566793607626">"მიმოხილვა"</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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"განბლოკვა"</string>
<string name="phone_label" msgid="2320074140205331708">"ტელეფონის გახსნა"</string>
<string name="camera_label" msgid="7261107956054836961">"კამერის გახსნა"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</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>
@@ -166,7 +165,7 @@
<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>
- <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"გადახედვა."</string>
+ <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"მიმოხილვა"</string>
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"მომხმარებელი: <xliff:g id="USER">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi გამორთულია."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"მობილური ქსელის წერტილი ჩაირთო."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"ეკრანის გადაცემა შეჩერებულია."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ეკრანის სიკაშკაშე"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G მონაც. გადაცემა გამორთულია"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G მონაც. გადაცემა გამორთულია"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ფიჭური ინტერნეტი გამორთულია"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"მონაცემთა გადაცემა გამორთულია"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"თქვენმა მოწყობილობამ მონაცემები გამორთო, რადგან თქვენ მიერ დაყენებულ ლიმიტს მიაღწია.\n\nმისი კვლავ გააქტიურებით შესაძლოა დაგეკისროთ გადასახადი თქვენი ოპერატორისგან."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"მონაცემთა ჩართვა"</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="4651001290947318931">"ფიჭური მონაცემები შეჩერებულია"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"მონაცემები შეჩერებულია"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"რადგან თქვენი მონაცემების ლიმიტი ამოწურულია, მოწყობილობამ შეაჭერა მონაცემების გამოყენება დარჩენილი ციკლისათვის. \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="gps_notification_searching_text" msgid="8574247005642736060">"GPS-ის ძებნა"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"დაიმალოს <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ის კვლავ გამოჩნდება, როდესაც პარამეტრებში ჩართავთ"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"დამალვა"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> სურს იყოს ხმოვან დიალოგში."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"უფლების მიცემა"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"უარყოფა"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index a57f71e..a6077a1 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"«Шолу» ішінде 1 экран"</item>
- <item quantity="other" msgid="5523506463832158203">"«Шолу» ішінде %d экран"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">«Шолу» ішінде %d экран</item>
+ <item quantity="one">«Шолу» ішінде 1 экран</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"бекітпесін ашу"</string>
<string name="phone_label" msgid="2320074140205331708">"телефонды ашу"</string>
<string name="camera_label" msgid="7261107956054836961">"камераны ашу"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Енгізу әдісі түймесін ауыстыру."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобильді хотспот қосылды."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Экранды трансляциялау тоқтатылды."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Дисплей жарықтығы"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G деректері өшірулі"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G деректері өшірулі"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Ұялы деректер өшірулі"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Деректер өшірулі"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Құрылғыңыз сіз орнатқан шекке жеткендіктен деректерді өшірді.\n\nОны қайтадан қосу оператордың ақылар алуына әкелуі мүмкін."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Деректерді қосу"</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="4651001290947318931">"Ұялы деректер кідіртілді"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Деректер кідіртілді"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Орнатылған деректер шегіне жеткендіктен, құрылғы осы циклдың қалған бөлігі бойы деректерді пайдалануды кідіртті.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS қызметін іздеуде"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жасыру керек пе?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ол сіз оны параметрлерде келесі қосқанда қайта пайда болады."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Жасыру"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> көлем диалогтық терезесі болғысы келеді."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Рұқсат беру"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Өшіру"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 9741b36..7e9eb9a 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"អេក្រង់ 1 ក្នុងទិដ្ឋភាព"</item>
- <item quantity="other" msgid="5523506463832158203">"អេក្រង់ %d ក្នុងទិដ្ឋភាព"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">អេក្រង់ %d ក្នុងទិដ្ឋភាព</item>
+ <item quantity="one">អេក្រង់ 1 ក្នុងទិដ្ឋភាព</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ដោះសោ"</string>
<string name="phone_label" msgid="2320074140205331708">"បើកទូរស័ព្ទ"</string>
<string name="camera_label" msgid="7261107956054836961">"បើកម៉ាស៊ីនថត"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរប៊ូតុងវិធីសាស្ត្របញ្ចូល។"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"បានបើកហតស្ប៉តចល័ត។"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"បានបញ្ឈប់ការចាត់ថ្នាក់អេក្រង់។"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ពន្លឺការបង្ហាញ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"ទិន្នន័យ 2G-3G បានបិទ"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"ទិន្នន័យ 4G បានបិទ"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ទិន្នន័យចល័តបានបិទ"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ទិន្នន័យបានបិទ"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"ឧបករណ៍របស់អ្នកបានបិទទិន្នន័យ ព្រោះវាបានដល់កម្រិតដែលអ្នកបានកំណត់។\n\nបើកវាឡើងវិញអាចគិតលុយពីក្រុមហ៊ុនបញ្ជូនរបស់អ្នក។"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"បើកទិន្នន័យ"</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="4651001290947318931">"ទិន្នន័យចល័តត្រូវបានផ្អាក"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ទិន្នន័យត្រូវបានផ្អាក"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ដោយសារទិន្នន័យរបស់អ្នកបានឈានដល់កំណត់ ឧបករណ៍នេះបានផ្អាកការប្រើប្រាស់ទិន្នន័យសម្រាប់ការរំលឹកនៃវគ្គនេះ។\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">"បានភ្ជាប់វ៉ាយហ្វាយ"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"ស្វែងរក GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"លាក់ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"វានឹងបង្ហាញពេលក្រោយ ពេលដែលអ្នកបើកក្នុងការកំណត់។"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"លាក់"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ចង់ក្លាយជាប្រអប់សម្លេង។"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"អនុញ្ញាត"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"បដិសេធ"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 5bfa66f..85fefec 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"ಸಮಗ್ರ ನೋಟದಲ್ಲಿರುವ 1 ಪರದೆ"</item>
- <item quantity="other" msgid="5523506463832158203">"ಸಮಗ್ರ ನೋಟದಲ್ಲಿರುವ %d ಪರದೆಗಳು"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"ಅಧಿಸೂಚನೆಗಳು"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ಅನ್ಲಾಕ್ ಮಾಡು"</string>
<string name="phone_label" msgid="2320074140205331708">"ಫೋನ್ ತೆರೆಯಿರಿ"</string>
<string name="camera_label" msgid="7261107956054836961">"ಕ್ಯಾಮರಾ ತೆರೆಯಿರಿ"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ಇನ್ಪುಟ್ ವಿಧಾನ ಬದಲಿಸು ಬಟನ್."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"ಮೊಬೈಲ್ ಹಾಟ್ಸ್ಪಾಟ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"ಸ್ಕ್ರೀನ್ ಪ್ರಸಾರವನ್ನು ನಿಲ್ಲಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ಹೊಳಪನ್ನು ಪ್ರದರ್ಶಿಸಿ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ಡೇಟಾ ಆಫ್ ಆಗಿದೆ"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ಡೇಟಾ ಆಫ್ ಆಗಿದೆ"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ಆಫ್ ಆಗಿದೆ"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ಡೇಟಾ ಆಫ್ ಆಗಿದೆ"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"ನೀವು ಹೊಂದಿಸಿದ ಮಿತಿಯನ್ನು ತಲುಪಿರುವ ಕಾರಣ ನಿಮ್ಮ ಸಾಧನವು ಡೇಟಾವನ್ನು ಆಫ್ ಮಾಡಿದೆ.\n\nಆನ್ ಮಾಡುವುದರಿಂದ ನಿಮ್ಮ ವಾಹಕದಲ್ಲಿ ಶುಲ್ಕಕ್ಕೆ ಕಾರಣವಾಗಬಹುದು."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ಡೇಟಾ ಆನ್ ಮಾಡಿ"</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="4651001290947318931">"ಸೆಲ್ಯುಲಾರ್ ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ಏಕೆಂದರೆ ನಿಮ್ಮ ಹೊಂದಾಣಿಕೆ ಡೇಟಾ ಮೀತಿಯನ್ನು ತಲುಪಿದೆ, ಈ ಆವರ್ತನೆಯ ಉಳಿದ ಭಾಗಕ್ಕೆ ಸಾಧನವು ಡೇಟಾ ಬಳಕೆಯನ್ನು ವಿರಾಮಗೊಳಿಸಿದೆ.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS ಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ಮರೆಮಾಡುವುದೇ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ನೀವು ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಅದನ್ನು ಆನ್ ಮಾಡಿದಾಗ ಅದು ಮರುಕಾಣಿಸಿಕೊಳ್ಳುತ್ತದೆ."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ಮರೆಮಾಡಿ"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಲು ಬಯಸುತ್ತದೆ."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ಅನುಮತಿಸು"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ನಿರಾಕರಿಸು"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 922e4c1..d6f8219 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"최근 사용에 화면 1개"</item>
- <item quantity="other" msgid="5523506463832158203">"최근 사용에 화면 %d개"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">최근 사용에 화면 %d개 있음</item>
+ <item quantity="one">최근 사용에 화면 1개 있음</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"잠금 해제"</string>
<string name="phone_label" msgid="2320074140205331708">"휴대전화 열기"</string>
<string name="camera_label" msgid="7261107956054836961">"카메라 열기"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"모바일 핫스팟을 사용합니다."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"화면 전송이 중지되었습니다."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"디스플레이 밝기"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G 데이터 사용 중지됨"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G 데이터 사용 중지됨"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"이동통신 데이터 사용 중지됨"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"데이터 사용 중지됨"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"데이터가 설정 한도에 도달하여 사용 중지되었습니다.\n\n데이터를 다시 사용 설정하면 이동통신사로부터 대금이 청구될 수 있습니다."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"데이터 사용 설정"</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="4651001290947318931">"모바일 데이터 사용 중지됨"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"데이터 사용 중지됨"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"설정된 데이터 한도에 도달했기 때문에 기기에서 사이클의 나머지 기간 동안 데이터 사용을 일시 중지했습니다. \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="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>을(를) 숨기시겠습니까?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"다음번에 설정에서 사용 설정하면 다시 표시됩니다."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"숨기기"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>이(가) 볼륨 대화가 되려고 합니다."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"허용"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"거부"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"원본을 복원하려면 터치하세요."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 6c54cb6..0029d67 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -27,10 +27,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 экран Көз жүгүртүүдө"</item>
- <item quantity="other" msgid="5523506463832158203">"%d экран Көз жүгүртүүдө"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d экран Көз жүгүртүүдө</item>
+ <item quantity="one">1 экран Көз жүгүртүүдө</item>
+ </plurals>
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -113,7 +113,6 @@
<string name="unlock_label" msgid="8779712358041029439">"кулпуну ачуу"</string>
<string name="phone_label" msgid="2320074140205331708">"телефонду ачуу"</string>
<string name="camera_label" msgid="7261107956054836961">"камераны ачуу"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Киргизүү ыкмасын которуу баскычы."</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>
@@ -226,12 +225,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобилдик байланыш түйүнү күйгүзүлдү."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Тышкы экранга чыгаруу аракети токтотулду."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Жарыктыгын көрсөтүү"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2Гб-3Гб көлөмдөгү дайындар өчүрүлдү."</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4Гб көлөмдөгү дайындар өчүрүлдү"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Уюктук дайындар тармагы өчүк"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Дайындарды кабыл алуу өчүрүлгөн."</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Белгиленген эң жогорку чекке жеткендиктен, түзмөгүңүз дайындарды кабыл алууну токтотту.\n\nДайындарды кабыл алууну улантам десеңиз, операторго акы төлөп калышыңыз мүмкүн."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Дайындарды алууну иштетүү"</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="4651001290947318931">"Уюлдук дайындар тындырылды"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Дайындар тындырылды"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Киргизиле турган дайындар белгиленген эң жогорку чекке жеткендиктен, ушул мерчимдин калган бөлүгүндө түзмөгүңүздө дайындардын колдонулушу тындырылды.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS издөө"</string>
@@ -394,4 +393,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жашырылсынбы?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Бул кийинки жолу жөндөөлөрдөн күйгүзүлгөндө кайра көрүнөт."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Жашыруу"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу болгусу келет."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Уруксат берүү"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Жок"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f205d0f..cc3d0cc0 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ຂໍ້ມູນແອັບຯ"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Your recent screens appear here"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ປິດແອັບຯຫຼ້າສຸດທີ່ໃຊ້"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ໜ້າຈໍຢູ່ໃນພາບຮວມ"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ໜ້າຈໍຢູ່ໃນພາບຮວມ"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d ໜ້າຈໍຢູ່ໃນພາບລວມ</item>
+ <item quantity="one">1 ໜ້າຈໍຢູ່ໃນພາບລວມ</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ປົດລັອກ"</string>
<string name="phone_label" msgid="2320074140205331708">"ເປີດແປ້ນໂທລະສັບ"</string>
<string name="camera_label" msgid="7261107956054836961">"ເປີດກ້ອງ"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"ເປີດຮັອດສະປອດເຄື່ອນທີ່ແລ້ວ."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"ຢຸດການສົ່ງພາບໜ້າຈໍແລ້ວ."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ຄວາມແຈ້ງຂອງຈໍ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"ຂໍ້ມູນ 2G-3G ແມ່ນປິດ"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"ຂໍ້ມູນ 4G ແມ່ນປິດ"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ຂໍ້ມູນມືຖືຖືກປິດ"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ຂໍ້ມູນຖືກປິດ"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"ອຸປະກອນຂອງທ່ານປິດການນຳໃຊ້ຂໍ້ມູນເນື່ອງຈາກມັນໃຊ້ຮອດຈຳນວນທີ່ທ່ານກຳນົດໄວ້ແລ້ວ.\n\nການເປີດນຳໃຊ້ຂໍ້ມູນຄືນອາດເຮັດໃຫ້ຜູ່ໃຫ້ບໍລິການຮຽກເກັບເງິນທ່ານເພີ່ມໄດ້."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ເປີດນຳໃຊ້ຂໍ້ມູນ"</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="4651001290947318931">"ຂໍ້ມູນເຊວລູລາຢຸດຊົ່ວຄາວແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ຂໍ້ມູນຢຸດຊົ່ວຄາວແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ເນື່ອງຈາກວ່າຮອດຂີດຈຳກັດຂໍ້ມູນທີ່ຕັ້ງໄວ້ຂອງທ່ານແລ້ວ, ອຸປະກອນຢຸດການນຳໃຊ້ຂໍ້ມູນສຳລັບສ່ວນທີ່ຍັງເຫຼືອຂອງຮອບວຽນນີ້.\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="gps_notification_searching_text" msgid="8574247005642736060">"ກຳລັງຊອກຫາ GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ເຊື່ອງ <xliff:g id="TILE_LABEL">%1$s</xliff:g> ຫຼືບໍ່?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ມັນຈະສະແດງຄືນໃໝ່ເມື່ອທ່ານເປີດນຳໃຊ້ມັນໃນການຕັ້ງຄ່າຄັ້ງຕໍ່ໄປ."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ເຊື່ອງ"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ຕ້ອງການໃຫ້ເປັນໜ້າຕ່າງລະດັບສຽງ."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ອະນຸຍາດ"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ປະຕິເສດ"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນໜ້າຕ່າງລະດັບສຽງ"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ສໍາຜັດເພື່ອກູ້ຄືນຕົ້ນສະບັບ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 5318844..b83f88f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -25,10 +25,12 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Programos informacija"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Čia rodomi naujausi ekranai"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Atsisakyti naujausių programų"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Ekranų apžvalga: 1"</item>
- <item quantity="other" msgid="5523506463832158203">"Ekranų apžvalga: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d ekrano apžvalga</item>
+ <item quantity="few">%d ekranų apžvalga</item>
+ <item quantity="many">%d ekrano apžvalga</item>
+ <item quantity="other">%d ekranų apžvalga</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nėra įspėjimų"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pranešimai"</string>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"atrakinti"</string>
<string name="phone_label" msgid="2320074140205331708">"atidaryti telefoną"</string>
<string name="camera_label" msgid="7261107956054836961">"atidaryti fotoaparatą"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Suderinamumo priartinimo mygtukas."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Padidinti ekraną."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"„Bluetooth“ prijungtas."</string>
@@ -201,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiliojo ryšio viešosios interneto prieigos taškas įjungtas."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ekrano perdavimas sustabdytas."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekrano šviesumas"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G duomenys išjungti"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G duomenys išjungti"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobiliojo ryšio duomenys išjungti"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Duomenys išjungti"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Įrenginys išjungė duomenis, nes buvo pasiektas nustatytas limitas.\n\nVėl juos įjungus gali būti taikomi operatoriaus mokesčiai."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Įjungti duomenis"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G duomenys pristabdyti"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G duomenys pristabdyti"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Korinio ryšio duomenys pristabdyti"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Duomenys pristabdyti"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kadangi buvo pasiektas nustatytas duomenų limitas, įrenginys pristabdė duomenų naudojimą likusį šio ciklo laikotarpį.\n\nAtnaujinus gali būti taikomi operatoriaus mokesčiai."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Atnaujinti"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nėra interneto ryš."</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Prisij. prie „Wi-Fi“"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
@@ -369,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Slėpti „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tai bus vėl parodyta, kai kitą kartą įjungsite tai nustatymuose."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Slėpti"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ nori būti garsumo valdymo dialogo langu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Leisti"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Atmesti"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d94c122..cc2702b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -25,10 +25,11 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Lietotnes informācija"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Jūsu pēdējie ekrāni tiek rādīti šeit."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Nerādīt nesen izmantotās lietotnes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ekrāns sadaļā “Pārskats”"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ekrāni sadaļā “Pārskats”"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="zero">%d ekrānu sadaļā Kopsavilkums</item>
+ <item quantity="one">%d ekrāns sadaļā Kopsavilkums</item>
+ <item quantity="other">%d ekrāni sadaļā Kopsavilkums</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nav paziņojumu"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
@@ -88,7 +89,6 @@
<string name="unlock_label" msgid="8779712358041029439">"atbloķēt"</string>
<string name="phone_label" msgid="2320074140205331708">"atvērt tālruni"</string>
<string name="camera_label" msgid="7261107956054836961">"atvērt kameru"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Saderības tālummaiņas poga."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Veikt tālummaiņu no mazāka ekrāna uz lielāku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth savienojums ir izveidots."</string>
@@ -201,12 +201,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilais tīklājs ir ieslēgts."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ekrāna apraidīšana ir apturēta."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekrāna spilgtums"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G dati ir atslēgti"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G dati ir atslēgti"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilie dati ir atslēgti"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dati ir atslēgti"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Jūsu ierīcē tika atslēgta datu lietošana, jo tika sasniegts jūsu noteiktais ierobežojums.\n\nJa atkal ieslēgsiet datu lietošanu, iespējams, jūsu mobilo sakaru operators iekasēs maksu."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ieslēgt datus"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G datu lietojums ir apturēts"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datu lietojums ir apturēts"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilo datu lietojums ir apturēts"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Datu lietojums ir apturēts"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Tika sasniegts iestatītais datu lietojuma ierobežojums, tādēļ ierīcē ir apturēts datu lietojums cikla atlikušajā periodā.\n\nJa atsāksiet lietot datus, iespējams, jūsu mobilo sakaru operators iekasēs maksu."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Atsākt"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Nav interneta sav."</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Izv. sav. ar Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
@@ -369,4 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vai paslēpt vienumu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Tas tiks atkārtoti parādīts, kad nākamreiz ieslēgsiet to iestatījumos."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Paslēpt"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> vēlas pārvaldīt skaļuma dialoglodziņu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Atļaut"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neatļaut"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index b606e33..a5bb833 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 екран во Краток преглед"</item>
- <item quantity="other" msgid="5523506463832158203">"%d екрани во Краток преглед"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"Во тек"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известувања"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"отклучи"</string>
<string name="phone_label" msgid="2320074140205331708">"отвори телефон"</string>
<string name="camera_label" msgid="7261107956054836961">"отвори камера"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Копче за префрање метод на внес."</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобилната точка на пристап е вклучена."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Емитувањето на екранот запре."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Осветленост на екранот"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Податоците 2G-3G се исклучени"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Податоците 4G се исклучени"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобилните податоци се исклучени"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Податоците се исклучени"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Вашиот уред ги исклучи податоците затоа што го достигнаа лимитот што го поставивте.\n\nСо повторно вклучување, операторот може да ви наплати за тоа."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Вклучи податоци"</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="4651001290947318931">"Мобилните податоци се паузирани"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Податоците се паузирани"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Поради тоа што го достигнавте поставеното ограничување на податоци, уредот го паузираше користењето податоци до крајот на циклусот.\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="gps_notification_searching_text" msgid="8574247005642736060">"Се пребарува за ГПС"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сокриј <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ќе се појави повторно следниот пат кога ќе го вклучите во поставки."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сокриј"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> сака да биде дијалог за јачина на звук."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Овозможи"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 6a65e6d..cc2188b 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"കാഴ്ചയിലെ ഒരു സ്ക്രീൻ"</item>
- <item quantity="other" msgid="5523506463832158203">"കാഴ്ചയിലെ %d സ്ക്രീനുകൾ"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">ചുരുക്കവിവരണത്തിലെ %d സ്ക്രീനുകൾ</item>
+ <item quantity="one">ചുരുക്കവിവരണത്തിലെ ഒരു സ്ക്രീൻ</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"അൺലോക്കുചെയ്യുക"</string>
<string name="phone_label" msgid="2320074140205331708">"ഫോൺ തുറക്കുക"</string>
<string name="camera_label" msgid="7261107956054836961">"ക്യാമറ തുറക്കുക"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ടൈപ്പുചെയ്യൽ രീതി ബട്ടൺ മാറുക."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"മൊബൈൽ ഹോട്ട്സ്പോട്ട് ഓണാക്കി."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"സ്ക്രീൻ കാസ്റ്റുചെയ്യൽ നിർത്തി."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ഡിസ്പ്ലേ തെളിച്ചം"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ഡാറ്റ ഓഫാണ്"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ഡാറ്റ ഓഫാണ്"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"സെല്ലുലാർ ഡാറ്റ ഓഫാണ്"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ഡാറ്റ ഓഫാണ്"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"നിങ്ങൾ സജ്ജീകരിച്ചിരിക്കുന്ന പരിധിയിൽ എത്തിച്ചേർന്നിരിക്കുന്നതിനാൽ ഉപകരണം ഡാറ്റ ഓഫുചെയ്തു.\n\nഅത് തിരികെ ഓണാക്കുന്നത്, നിങ്ങളുടെ കാരിയറിൽ നിന്ന് നിരക്കീടാക്കുന്നതിന് ഇടയാക്കാം."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ഡാറ്റ ഓണാക്കുക"</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="4651001290947318931">"സെല്ലുലാർ ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"നിങ്ങൾ നേരത്തെ ക്രമീകരിച്ച ഡാറ്റ പരിധിയിലെത്തിയതിനാൽ, ഈ സൈക്കിളിന്റെ അവശേഷിക്കുന്ന ഡാറ്റ ഉപയോഗം, ഉപകരണം താൽക്കാലികമായി നിർത്തി.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS-നായി തിരയുന്നു"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> എന്നത് മറയ്ക്കണോ?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"അടുത്ത തവണ നിങ്ങൾ അത് ക്രമീകരണങ്ങളിൽ ഓണാക്കുമ്പോൾ അത് വീണ്ടും ദൃശ്യമാകും."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"മറയ്ക്കുക"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗ് ആകാൻ താൽപ്പര്യപ്പെടുന്നു."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"അനുവദിക്കുക"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"നിരസിക്കുക"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"ആദ്യത്തേത് പുനഃസ്ഥാപിക്കാൻ സ്പർശിക്കുക."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 1d53b17..fd16012 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -25,10 +25,8 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"Тойм дээр 1 дэлгэц"</item>
- <item quantity="other" msgid="5523506463832158203">"Тойм дээрх %d дэлгэц"</item>
- </plurals>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for status_bar_accessibility_recent_apps (9138535907802238759) -->
<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>
@@ -88,7 +86,6 @@
<string name="unlock_label" msgid="8779712358041029439">"тайлах"</string>
<string name="phone_label" msgid="2320074140205331708">"утас нээх"</string>
<string name="camera_label" msgid="7261107956054836961">"камер нээх"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</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>
@@ -201,12 +198,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобайл хотспотыг асаасан."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Дэлгэц дамжуулалт зогссон."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Дэлгэцийн гэрэлтэлт"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G дата идэвхгүй"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G дата идэвхгүй"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Үүрэн дата идэвхгүй"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Дата идэвхгүй"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Таны тогтоосон хязгаарт хүрсэн учир төхөөрөмж датаг унтраасан.\n\nҮүнийг асааснаар таны төлбөр нэмэгдэхэд хүргэж болзошгүй."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Датаг асаах"</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="4651001290947318931">"Гар утасны дата-г түр зогсоосон байна"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Дата-г түр зогсоосон байна"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Таны багц дата эрхийн дээд хэмжээнд хүрсэн байгаа тул төхөөрөмж нь үлдсэн хэсэгт дата хэрэглээг түр зогсоосон байна.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS хайж байна"</string>
@@ -369,4 +366,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>-ийг нуух уу?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Тохируулгын хэсэгт үүнийг асаахад энэ дахин харагдана."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Нуух"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог болохыг хүсч байна."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Зөвшөөрөх"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Татгалзах"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Анхны хувилбарыг эргүүлэн хадгалахыг хүсвэл хүрнэ үү."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index dc5f649..afaa65d 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"विहंगावलोकनात 1 स्क्रीन"</item>
- <item quantity="other" msgid="5523506463832158203">"विहंगावलोकनात %d स्क्रीन"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"सुरु असलेले"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचना"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"अनलॉक करा"</string>
<string name="phone_label" msgid="2320074140205331708">"फोन उघडा"</string>
<string name="camera_label" msgid="7261107956054836961">"कॅमेरा उघडा"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धत स्विच करा बटण."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"मोबाईल हॉटस्पॉट चालू केला."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"स्क्रीन कास्ट करणे थांबले."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G डेटा बंद आहे"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G डेटा बंद आहे"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"सेल्युलर डेटा बंद आहे"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"डेटा बंद आहे"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"डेटाने आपण सेट केलेली मर्यादा गाठल्यामुळे आपल्या डिव्हाइसने तो बंद केला.\n\n तो पुन्हा चालू केल्यास आपल्या वाहकाकडील शुल्क लागू शकेल."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"डेटा चालू करा"</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="4651001290947318931">"सेल्युलर डेटास विराम दिला आहे"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटास विराम दिला आहे"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"आपली सेट केलेली डेटा मर्यादा गाठल्यामुळे, डिव्हाइसने या चक्राच्या उर्वरित डेटा वापरास विराम दिला आहे.\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">"वाय-फाय कनेक्ट केले"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS शोधत आहे"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> लपवायचे?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"आपण सेटिंग्जमध्ये ते पुढील वेळी चालू कराल तेव्हा ते पुन्हा दिसेल."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"लपवा"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद होऊ इच्छितो."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमती द्या"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"नकार द्या"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 4188bd5..d0f3213 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Maklumat aplikasi"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Skrin terbaru anda terpapar di sini"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Buang aplikasi terbaharu"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 skrin dalam Ikhtisar"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skrin dalam Ikhtisar"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d skrin dalam Gambaran Keseluruhan</item>
+ <item quantity="one">1 skrin dalam Gambaran Keseluruhan</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tiada pemberitahuan"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sedang berlangsung"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"buka kunci"</string>
<string name="phone_label" msgid="2320074140205331708">"buka telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"buka kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Butang zum keserasian."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Skrin zum lebih kecil kepada lebih besar."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth disambungkan."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Tempat liputan mudah alih bergerak dihidupkan."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Penghantaran skrin dihentikan."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan paparan"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data 2G-3G dimatikan"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data 4G dimatikan"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Data selular dimatikan"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data dimatikan"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Peranti anda mematikan data kerana telah mencapai had yang anda tetapkan.\n\nMenghidupkan data semula boleh menyebabkan anda dikenakan caj oleh pembawa anda."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Hidupkan data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data selular dijeda"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data dijeda"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Oleh kerana had data tetap anda telah dicapai, peranti telah menjeda penggunaan data bagi baki kitaran ini.\n\nMenyambung semula boleh menyebabkan anda dikenakan bayaran daripada pembawa anda."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Sambung semula"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Tiada smbg Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi disambungkan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Mencari GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Mesej itu akan terpapar semula pada kali seterusnya anda menghidupkan apl dalam tetapan."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Sembunyikan"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> mahu menjadi dialog kelantangan."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Benarkan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 46ba92c..b572ba2 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"ခြုံကြည့်မှု ထဲက မျက်နှာပြင် ၁ ခု"</item>
- <item quantity="other" msgid="5523506463832158203">"ခြုံကြည့်မှု ထဲက မျက်နှာပြင် %d ခု"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">ခြုံကြည့်မှုထဲမှ မျက်နှာပြင် %d ခု</item>
+ <item quantity="one">ခြုံကြည့်မှုထဲမှ မျက်နှာပြင် 1 ခု</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"သော့ဖွင့်ရန်"</string>
<string name="phone_label" msgid="2320074140205331708">"ဖုန်းကို ဖွင့်ရန်"</string>
<string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ထည့်သွင်းခြင်းခလုတ်အား ပြောင်းခြင်း"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"မိုဘိုင်း ဟော့စပေါ့ ဖွင့်ထား။"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"မျက်နှာပြင် ကာစ်တင် လုပ်မှု ရပ်လိုက်ပြီ။"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ဒေတာ ပိတ်ထား"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ဒေတာ ပိတ်ထား"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ဆယ်လူလာ ဒေတာကို ပိတ်ထား"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ဒေတာ ပိတ်ထား"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"သင်၏ ကိရိယာသည် သင်က သတ်မှတ်ခဲ့သည့် ကန့်သတ်ချက်ကို ပြည့်မီသွား၍ ပိတ်သွားသည်။ \n\n၎င်းကို ပြန်ပြီး ဖွင့်မှုအတွက် သင်၏ စီမံပေးသူ ထံမှ ငွေတောင်းခံ လာနိုင်ပါသည်။"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ဒေတာ ဖွင့်ပေးရန်"</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 data ခေတ္တရပ်တန့်သည်"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"cellular data ခေတ္တရပ်တန့်သည်"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ဒေတာ ခေတ္တရပ်တန့်သည်"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"သင့် ဒေတာ အသုံးပြုမှု သတ်မှတ်ထားချက်သို့ ရောက်ရှိသောကြောင့်၊ ဤကာလအတွက် ကျန်ရှိသည့် ဒေတာအသုံးပြုမှုအား စက်ပစ္စည်းမှ ရပ်တန့်ထားသည်။\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">"ကြိုးမဲ့ဆက်သွယ်မှု"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSအားရှာဖွေသည်"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ဝှက်မည်လား?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"နောက်တစ်ကြိမ်သင် ချိန်ညှိချက်များဖွင့်လျှင် ၎င်းပေါ်လာပါမည်။"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ဖျောက်ထားမည်"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည်အသံဒိုင်ယာလော့ခ်ဖြစ်လိုပါသည်။"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ခွင့်ပြုသည်"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ငြင်းပယ်သည်"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9e87307..b78723c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Info om appen"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"De sist brukte skjermene dine vises her"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Avvis nylige apper"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 skjerm i Oversikten"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skjermer i Oversikten"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d skjermer i oversikten</item>
+ <item quantity="one">1 skjerm i oversikten</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"lås opp"</string>
<string name="phone_label" msgid="2320074140205331708">"åpne telefonen"</string>
<string name="camera_label" msgid="7261107956054836961">"åpne kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Zoomknapp for kompatibilitet."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom fra mindre til større skjerm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth er tilkoblet."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobil Wi-Fi-sone er slått på."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Skjermcastingen er stoppet."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Lysstyrken på skjermen"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G- og 3G-data er slått av"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-datatrafikk er slått av"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobildatatrafikk er slått av"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Datatrafikk er slått av"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Datatrafikk er slått av på enheten din fordi du har nådd den angitte grensen.\n\nHvis du slår datatrafikken på igjen, kan det føre til belastninger fra operatøren din."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Slå på datatrafikk"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- og 3G-data er satt på pause"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er satt på pause"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata er satt på pause"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data er satt på pause"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Fordi den angitte datagrensen ble nådd, har enheten satt databruk på pause for resten av denne syklusen. \n\nHvis du gjenopptar bruken, kan det føre til avgifter fra operatøren din."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Gjenoppta"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen Internett-forbindelse"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tilkoblet"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igjen neste gang du slår den på i innstillingene."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ønsker å være volumdialogen."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillat"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ikke tillat"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 7ccab6b..45e338a 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"सारांशमा 1 पर्दा"</item>
- <item quantity="other" msgid="5523506463832158203">"सारांशमा %d पर्दाहरू"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other"> अवलोकनमा %d स्क्रिनहरू</item>
+ <item quantity="one">अवलोकनमा 1 स्क्रिन</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"खोल्नुहोस्"</string>
<string name="phone_label" msgid="2320074140205331708">"फोन खोल्नुहोस्"</string>
<string name="camera_label" msgid="7261107956054836961">"क्यामेरा खोल्नुहोस्"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट विधि बटन स्विच गर्नुहोस्।"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"मोबाइल हटस्पट खुला गरियो।"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"स्क्रिन कास्टिङ रोकियो।"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G डेटा बन्द छ"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G डेटा बन्द छ"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"सेलुलर डेटा बन्द छ"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"डेटा बन्द छ"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"तपाईंले सेट गर्नु भएको सीमा पुगेको हुनाले तपाईंको उपकरणले डेटा बंद गर्यो।\n\n यसलाई फिर्ता गर्दा आफ्नो वाहक बाट शुल्क लिन सक्छ।"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"डेटा खोल्नुहोस्"</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="4651001290947318931">"सेल्यूलर डेटा रोकिएको छ"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"डेटा रोकिएको छ"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"तपाईंले सेट गर्नुभएको डेटाको सीमा पुगेकाले, यन्त्रले यस चक्रको बाँकी भागका लागि डेटा प्रयोग रोकेको छ।\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">"वाइफाइ जडित"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSको लागि खोजी गर्दै"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"लुकाउनुहुन्छ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"यो तपाईं सेटिङ् मा यो बारी अर्को समय देखापर्नेछ।"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"लुकाउनुहोस्"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद बन्न चाहन्छ।"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"अनुमति दिनुहोस्"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार गर्नुहोस्"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुनर्स्थापना गर्न छुनुहोस्।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 4170534..4006618 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"App-info"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Uw recente schermen worden hier weergegeven"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Recente apps negeren"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 scherm in Overzicht"</item>
- <item quantity="other" msgid="5523506463832158203">"%d schermen in Overzicht"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d schermen in Overzicht</item>
+ <item quantity="one">1 scherm in Overzicht</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ontgrendelen"</string>
<string name="phone_label" msgid="2320074140205331708">"telefoon openen"</string>
<string name="camera_label" msgid="7261107956054836961">"camera openen"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knop voor compatibiliteitszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kleiner scherm uitzoomen naar groter scherm."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-verbinding ingesteld."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobiele hotspot ingeschakeld."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Casten van scherm gestopt."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Helderheid van het scherm"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G/3G-data zijn uitgeschakeld"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-data zijn uitgeschakeld"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobiele data zijn uitgeschakeld"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Gegevens zijn uitgeschakeld"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Uw apparaat heeft gegevens uitgeschakeld omdat de ingestelde limiet is bereikt.\n\nAls u gegevens weer inschakelt, kan uw provider kosten in rekening brengen."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Gegevens inschakelen"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G/3G-data zijn onderbroken"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data zijn onderbroken"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobiele gegevens zijn onderbroken"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Gegevens zijn onderbroken"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Omdat de ingestelde gegevenslimiet is bereikt, heeft het apparaat het gegevensverbruik onderbroken voor de rest van deze cyclus.\n\nAls u het gegevensverbruik hervat, kan uw provider kosten in rekening brengen."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Hervatten"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Geen internetverbinding"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Verbonden via wifi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> verbergen?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Deze wordt opnieuw weergegeven zodra u de instelling weer inschakelt."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Verbergen"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> wil het volumedialoogvenster zijn."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Toestaan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afwijzen"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 72a5944..1b9e1d4 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -25,10 +25,12 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informacje o aplikacji"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Tutaj pojawią się ostatnie ekrany"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ukryj ostatnie aplikacje"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ekran w widoku przeglądu"</item>
- <item quantity="other" msgid="5523506463832158203">"Ekrany w widoku przeglądu: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="few">%d ekrany w widoku przeglądu</item>
+ <item quantity="many">%d ekranów w widoku przeglądu</item>
+ <item quantity="other">%d ekranu w widoku przeglądu</item>
+ <item quantity="one">1 ekran w widoku przeglądu</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"odblokuj"</string>
<string name="phone_label" msgid="2320074140205331708">"otwórz telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"otwórz aparat"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Przycisk powiększenia na potrzeby zgodności."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Powiększa mniejszy ekran do większego."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth połączony."</string>
@@ -201,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilny hotspot został włączony."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Zatrzymano przesyłanie ekranu."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Jasność wyświetlacza"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Połączenie danych 2G-3G wyłączone"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Połączenie danych 4G wyłączone"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Komórkowe połączenie danych jest wyłączone"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Połączenie danych jest wyłączone"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Połączenie danych na Twoim urządzeniu zostało wyłączone, ponieważ osiągnęło ustalony limit.\n\nJeśli włączysz je ponownie, operator może naliczyć opłaty."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Włącz połączenie danych"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Transmisja danych 2G-3G została wstrzymana"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Transmisja danych 4G została wstrzymana"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Komórkowa transmisja danych została wstrzymana"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Transmisja danych została wstrzymana"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ponieważ został osiągnięty ustawiony przez Ciebie limit danych, urządzenie wstrzymało użycie danych na pozostałą część tego cyklu.\n\nWznowienie może spowodować naliczenie opłat przez operatora."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Wznów"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Brak internetu"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
@@ -250,7 +251,7 @@
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi wyłączone"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Brak dostępnych zapisanych sieci"</string>
- <string name="quick_settings_cast_title" msgid="1893629685050355115">"Przesyłaj ekran"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Prześlij ekran"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Urządzenie bez nazwy"</string>
<string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Wszystko gotowe do przesyłania"</string>
@@ -369,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ukryć <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Pojawi się ponownie, gdy następnym włączysz go w ustawieniach."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ukryj"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce sterować głośnością."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Zezwól"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmów"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8f854a6..4cdb511 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informações da aplicação"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Os ecrãs recentes aparecem aqui"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicações recentes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ecrã na Visão geral"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ecrãs na Visão geral"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d ecrãs na Vista geral</item>
+ <item quantity="one">1 ecrã na Vista geral</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
<string name="phone_label" msgid="2320074140205331708">"abrir telemóvel"</string>
<string name="camera_label" msgid="7261107956054836961">"abrir câmara"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão zoom de compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom menor para ecrã maior."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ligado."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Zona Wi-Fi móvel ligada."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Transmissão do ecrã interrompida."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brilho do visor"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Dados 2G-3G desligados"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Dados 4G desligados"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Dados de rede móvel desligados"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dados desligados"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"O dispositivo desligou os dados porque atingiu o limite definido.\n\nVoltar a ligá-los pode resultar em cobranças por parte do operador."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ligar dados"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dados 2G-3G em pausa"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dados 4G em pausa"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Dados de redes móveis em pausa"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dados em pausa"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Uma vez que foi atingido o limite de dados definido, foi interrompida a utilização de dados no seu dispositivo durante o tempo restante deste ciclo.\n\nSe retomar a utilização, o seu operador pode efetuar cobranças."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sem ligação internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ligado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"A procurar GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Pretende ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Reaparecerá da próxima vez que a funcionalidade for ativada nas definições."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> pretende ser a caixa de diálogo do volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Recusar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 889d3ec..461ac26 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informações do app"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Suas telas recentes aparecem aqui"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Dispensar apps recentes"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 tela em \"Visão geral\""</item>
- <item quantity="other" msgid="5523506463832158203">"%d telas em \"Visão geral\""</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d telas em \"Visão geral\"</item>
+ <item quantity="other">%d telas em \"Visão geral\"</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"desbloquear"</string>
<string name="phone_label" msgid="2320074140205331708">"abrir telefone"</string>
<string name="camera_label" msgid="7261107956054836961">"abrir câmera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Botão de zoom da compatibilidade."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Aumentar a tela com zoom."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth conectado."</string>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"O ponto de acesso móvel foi ativado."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"A transmissão de tela foi interrompida."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Os dados 2G-3G foram desativados"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Os dados 4G foram desativados"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Os dados da rede celular foram desativados"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Os dados foram desativados"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"O dispositivo desativou os dados porque o limite definido foi atingido.\n\nAtivá-los novamente poderá resultar em cobranças de sua operadora."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Ativar dados"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Os dados da rede celular foram pausados"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Os dados foram pausados"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Como seu limite de dados definido foi atingido, o dispositivo pausou o uso de dados para o restante deste ciclo.\n\nA retomada pode gerar cobranças por parte da sua operadora."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Retomar"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Sem conexão à Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ela reaparecerá na próxima vez que você ativá-la nas configurações."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> deseja ser a caixa de diálogo referente ao volume."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permitir"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 159d0be..fbaf763 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -25,10 +25,11 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informaţii despre aplicaţie"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Ecranele dvs. recente apar aici"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Renunţaţi la aplicaţiile recente"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 ecran în Vizualizare generală"</item>
- <item quantity="other" msgid="5523506463832158203">"%d ecrane în Vizualizare generală"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="few">%d ecrane în Recente</item>
+ <item quantity="other">%d de ecrane în Recente</item>
+ <item quantity="one">Un ecran în Recente</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nicio notificare"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfăşurare"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
@@ -88,7 +89,6 @@
<string name="unlock_label" msgid="8779712358041029439">"deblocați"</string>
<string name="phone_label" msgid="2320074140205331708">"deschideți telefonul"</string>
<string name="camera_label" msgid="7261107956054836961">"deschideți camera foto"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Buton zoom pentru compatibilitate."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Faceţi zoom de la o imagine mai mică la una mai mare."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Conectat prin Bluetooth."</string>
@@ -201,12 +201,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Hotspotul mobil este activat."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Transmiterea ecranului a fost oprită."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Luminozitatea ecranului"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Datele 2G-3G sunt dezactivate"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Datele 4G sunt dezactivate"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Datele mobile sunt dezactivate"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Datele sunt dezactivate"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Dispozitivul dvs. a dezactivat conexiunea de date deoarece s-a atins limita pe care ați setat-o.\n\nReactivarea conexiunii poate genera aplicarea de taxe de către operator."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Activați datele"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Conexiunea de date 2G – 3G este întreruptă"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Conexiunea de date 4G este întreruptă"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Conexiunea de date mobile este întreruptă"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Conexiunea de date este întreruptă"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Deoarece limita setată pentru date a fost atinsă, dispozitivul a întrerupt utilizarea datelor pentru restul acestui ciclu.\n\nReluarea utilizării de date poate genera aplicarea de taxe de către operator."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Reluați"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Fără conex. internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
@@ -369,4 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ascundeți <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Va reapărea la următoarea activare în setări."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ascundeți"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> dorește să afișeze caseta de dialog pentru volum."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Permiteți"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzați"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 3ea47ec..b57ccb3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -25,10 +25,12 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"В обзоре 1 экран."</item>
- <item quantity="other" msgid="5523506463832158203">"Экранов в обзоре: %d."</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">Показан %d экран</item>
+ <item quantity="few">Показано %d экрана</item>
+ <item quantity="many">Показано %d экранов</item>
+ <item quantity="other">Показано %d экранов</item>
+ </plurals>
<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>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"Разблокировать."</string>
<string name="phone_label" msgid="2320074140205331708">"Открыть телефон."</string>
<string name="camera_label" msgid="7261107956054836961">"Открыть камеру."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</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>
@@ -203,12 +204,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Точка доступа включена."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Трансляция прекращена."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Яркость экрана"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Передача данных 2G/3G отключена"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Передача данных 4G отключена"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Передача мобильных данных отключена"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Передача данных отключена"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Передача данных отключена, поскольку достигнут установленный вами лимит.\n\nВы можете снова включить ее, однако за переданные данные оператор может взимать дополнительную плату."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Включить передачу данных"</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="4651001290947318931">"Передача мобильных данных приостановлена"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Передача данных приостановлена"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Передача данных выключена до конца цикла, поскольку достигнут установленный вами лимит.\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="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
@@ -371,4 +372,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Скрыть параметр \"<xliff:g id="TILE_LABEL">%1$s</xliff:g>\"?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Этот параметр появится в следующий раз, когда вы включите его."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Скрыть"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Назначить приложение <xliff:g id="APP_NAME">%1$s</xliff:g> регулятором громкости?"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Да"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Нет"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index a488050..e6ec65f 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"දළ විශ්ලේෂණය තුළ 1 තීරයයි"</item>
- <item quantity="other" msgid="5523506463832158203">"දළ විශ්ලේෂණය තුළ තීරයෙන් %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <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_ongoing_events_title" msgid="1682504513316879202">"දැනට පවතින"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"දැනුම්දීම්"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"අඟුල අරින්න"</string>
<string name="phone_label" msgid="2320074140205331708">"දුරකථනය විවෘත කරන්න"</string>
<string name="camera_label" msgid="7261107956054836961">"කැමරාව විවෘත කරන්න"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ආදාන ක්රමය මාරු කිරීමේ බොත්තම."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"ජංගම හොට්ස්පොටය සක්රිය කරන ලදි."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"තිරය විකාශය කිරීම නැවත් වන ලදි."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"දීප්තිය දර්ශනය කරන්න"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G දත්ත අක්රියයි"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G දත්ත අක්රියයි"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"සෙලියුලර් දත්ත අක්රියයි"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"දත්ත අක්රියයි"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"ඔබ සකසන ලද දත්ත සීමාවට එය ළඟාවී ඇති නිසා ඔබගේ උපාංගයේ දත්ත අක්රිය කර ඇත.\n\nඑය නැවත සක්රිය කිරීමෙන් ඔබගේ වාහකය ඇතැම් විට අය කර ගැනීමට හේතු වේ."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"දත්ත සක්රිය කරන්න"</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="4651001290947318931">"සෙලියුලර් දත්ත විරාම කර ඇත"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"දත්ත විරාම කර ඇත"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"ඔබ සකසා ඇති දත්ත සීමාවට ළඟා වූ නිසා, උපාංගය මගින් මෙම චක්රයේ ඉතිරිය සඳහා දත්ත භාවිතය විරාම කර ඇත. \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="gps_notification_searching_text" msgid="8574247005642736060">"GPS සඳහා සොයමින්"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> සඟවන්නද?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"ඊළඟ අවස්ථාවේ සැකසීම් තුළ ඔබ එය සක්රිය කළ විට එය නැවත දිසිවේ."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"සඟවන්න"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> හට ධාරිතා සංවාදය වීමට අවශ්යයි"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"ඉඩ දෙන්න"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ප්රතික්ෂේප කරන්න"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්ත්වය නැවත ප්රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index e9ded7c..eba3977 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -25,10 +25,12 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informácie o aplikácii"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Vaše nedávne obrazovky sa zobrazia tu."</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Zatvoriť nedávne aplikácie"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Počet obrazoviek v Prehľade: 1"</item>
- <item quantity="other" msgid="5523506463832158203">"Počet obrazoviek v Prehľade: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="few">%d obrazovky v Prehľade</item>
+ <item quantity="many">%d obrazovky v Prehľade</item>
+ <item quantity="other">%d obrazoviek v Prehľade</item>
+ <item quantity="one">1 obrazovka v Prehľade</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žiadne upozornenia"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"odomknúť"</string>
<string name="phone_label" msgid="2320074140205331708">"otvoriť telefón"</string>
<string name="camera_label" msgid="7261107956054836961">"spustiť fotoaparát"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Tlačidlo úpravy veľkosti z dôvodu kompatibility."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zväčšiť menší obrázok na väčšiu obrazovku."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth pripojené."</string>
@@ -203,12 +204,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilný hotspot je zapnutý."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Prenášanie bolo zastavené."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeja"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"dáta 2G–3G sú vypnuté"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"dáta 4G sú vypnuté"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobilné dáta sú vypnuté"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dáta sú vypnuté"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Zariadenie vyplo dáta, pretože dosiahlo limit, ktorý ste nastavili.\n\nAk ich znova zapnete, môže to viesť k účtovaniu poplatkov operátora."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Zapnúť dáta"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dátové prenosy 2G a 3G sú pozastavené"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dátové prenosy 4G sú pozastavené"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilné dáta sú pozastavené"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dáta sú pozastavené"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Keďže ste dosiahli nastavený limit pre mobilné dáta, na zariadení bola pre zvyšok tohto cyklu pozastavená spotreba dát.\n\nJej opätovné spustenie môže mať za následok účtovanie poplatkov vaším operátorom."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Znova spustiť"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Bez prip. na Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: pripojené"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
@@ -371,4 +372,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skryť <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Táto položka sa znova zobrazí, keď ju v nastaveniach opätovne zapnete."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skryť"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> chce byť dialógom hlasitosti"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Povoliť"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmietnuť"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 89f90e5..65d684b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -25,10 +25,12 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Podatki o aplikaciji"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Vaši nedavni zasloni so prikazani tu"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Zapre nedavne aplikacije"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"En zaslon v Pregledu"</item>
- <item quantity="other" msgid="5523506463832158203">"Št. zaslonov v Pregledu: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d zaslon v pregledu</item>
+ <item quantity="two">%d zaslona v pregledu</item>
+ <item quantity="few">%d zasloni v pregledu</item>
+ <item quantity="other">%d zaslonov v pregledu</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ni obvestil"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"odkleni"</string>
<string name="phone_label" msgid="2320074140205331708">"odpri telefon"</string>
<string name="camera_label" msgid="7261107956054836961">"odpri fotoaparat"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Gumb povečave za združljivost."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Povečava manjšega na večji zaslon."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Povezava Bluetooth vzpostavljena."</string>
@@ -201,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobilna dostopna točka je vklopljena."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Predvajanje zaslona je ustavljeno."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Svetlost zaslona"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Prenos podatkov v omrežjih 2G/3G je izklopljen"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Prenos podatkov v omrežjih 4G je izklopljen"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Prenos podatkov v mobilnih omrežjih je izklopljen"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Prenos podatkov je izklopljen"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Naprava je izklopila prenos podatkov, ker je bila dosežena omejitev, ki ste jo nastavili.\n\nČe prenos spet vklopite, vam bo operater morda zaračunal stroške."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Vklopi prenos podatkov"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Prenos podatkov v omrežju 2G/3G je zaustavljen"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Prenos podatkov v omrežju 4G je zaustavljen"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Prenos mobilnih podatkov je zaustavljen"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Prenos podatkov je zaustavljen"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Dosegli ste nastavljeno omejitev količine prenesenih podatkov, zato je naprava zaustavila porabo podatkov za preostanek cikla.\n\nČe nadaljujete s porabo, boste morda morali plačati stroške operaterju."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nadaljuj"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ni internetne povez."</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Iskanje GPS-a"</string>
@@ -369,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite skriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Znova se bo pojavila, ko jo naslednjič vklopite v nastavitvah."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skrij"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> želi biti pogovorno okno glede prostornine."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Dovoli"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Zavrni"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index ee907de..fca2a8a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -25,10 +25,11 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 екран у Прегледу"</item>
- <item quantity="other" msgid="5523506463832158203">"%d екрана у Прегледу"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d екран у Прегледу</item>
+ <item quantity="few">%d екрана у Прегледу</item>
+ <item quantity="other">%d екрана у Прегледу</item>
+ </plurals>
<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>
@@ -88,7 +89,6 @@
<string name="unlock_label" msgid="8779712358041029439">"откључај"</string>
<string name="phone_label" msgid="2320074140205331708">"отвори телефон"</string>
<string name="camera_label" msgid="7261107956054836961">"отвори камеру"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</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>
@@ -201,12 +201,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобилни хотспот је укључен."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Пребацивање екрана је заустављено."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Осветљеност екрана"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G–3G подаци су искључени"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G подаци су искључени"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобилни пренос података је искључен"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Пренос података је искључен"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Уређај је искључио пренос података јер је достигао ограничење које сте поставили.\n\nАко га поново укључите, можда ће вам мобилни оператер наплатити трошкове."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Укључи пренос података"</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="4651001290947318931">"Мобилни подаци су паузирани"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Подаци су паузирани"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Због тога што сте достигли подешено ограничење за податке, уређај је паузирао коришћење података током остатка овог циклуса.\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="gps_notification_searching_text" msgid="8574247005642736060">"Тражи се GPS"</string>
@@ -369,4 +369,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Желите ли да сакријете <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ово ће се поново појавити када га следећи пут будете укључили у подешавањима."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сакриј"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> жели да буде дијалог за јачину звука."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Дозволи"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 9b9bda0..020e777 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Info om appen"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Dina senaste skärmar visas här"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Avvisa nya appar"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"En skärm i Översikten"</item>
- <item quantity="other" msgid="5523506463832158203">"%d skärmar i Översikten"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d skärmar i översikten</item>
+ <item quantity="one">En skärm i översikten</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"lås upp"</string>
<string name="phone_label" msgid="2320074140205331708">"öppna mobilen"</string>
<string name="camera_label" msgid="7261107956054836961">"öppna kameran"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Knapp för kompatibilitetszoom."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zooma mindre skärm till större."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ansluten."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Den mobila trådlösa surfzonen har aktiverats."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Castningen av skärmen har stoppats."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Skärmens ljusstyrka"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-/3G-data har inaktiverats"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G-data har inaktiverats"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobildata har inaktiverats"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data har inaktiverats"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Data har stängts av på enheten eftersom den angivna gränsen har uppnåtts.\n\nOm du aktiverar den igen kan avgifter från operatören tillkomma."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Aktivera uppgifter"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- och 3G-data har pausats"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data har pausats"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobildata har pausats"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Dataanvändningen har pausats"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Eftersom du har nått den angivna datagränsen har dataanvändningen pausats under resten av perioden.\n\nOm du återupptar dataanvändningen kan avgifter från operatören tillkomma."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Återuppta"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ingen anslutning"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ansluten"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Sökning efter GPS pågår"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vill du dölja <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den visas på nytt nästa gång du aktiverar den i inställningarna."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Dölj"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> försöker överta funktionen som volymkontroll."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Tillåt"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neka"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c512731..ca4baee 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Taarifa za programu-matumizi"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Skrini zako za hivi majuzi huonekana hapa"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ondosha programu za hivi karibuni"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Skrini 1 katika Muhtasari"</item>
- <item quantity="other" msgid="5523506463832158203">"Skrini %d katika Muhtasari"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">Skrini %d katika Muhtasari</item>
+ <item quantity="one">Skrini 1 katika Muhtasari</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Hakuna arifa"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Inaendelea"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Arifa"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"fungua"</string>
<string name="phone_label" msgid="2320074140205331708">"fungua simu"</string>
<string name="camera_label" msgid="7261107956054836961">"fungua kamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kichupo cha kukuza kwa utangamanifu"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kuza kidogo kwa skrini kubwa."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth imeunganishwa."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mtandao-hewa unaoweza kuhamishika umewashwa."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Utumaji wa skrini umesitishwa."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ung\'aavu wa skrini"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Data ya 2G-3G imezimwa"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Data ya 4G imezimwa"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Data ya simu ya mkononi imezimwa"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Data imezimwa"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Kifaa chako kilizima data kwa sababu kilifikia kikomo ulichoweka.\n\nKuwasha data tena kunaweza kusababisha matozo kutoka kwa mtoa huduma wako."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Washa matumizi ya data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data ya 2G-3G imesitishwa"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data ya 4G imesitishwa"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Data ya simu ya mkononi imesitishwa"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Data imesitishwa"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Kwa sababu ulifikia kiwango cha juu cha data kilichowekwa, kifaa kimesitisha matumizi ya data katika awamu hii iliyosalia.\n\n Kuendelea kunaweza kusababisha malipo kwa mtoa huduma wako."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Endelea"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Hakuna muunganisho wa mtandao"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Mtandao-hewa umeunganishwa"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Inatafuta GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ungependa kuficha <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Itaonekana tena wakati mwingine utakapoiwasha katika mipangilio."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ficha"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> inataka kuwa mazungumzo ya sauti."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Ruhusu"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Kataa"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 9a08476..b716bda 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"மேலோட்டப் பார்வையில் 1 திரை"</item>
- <item quantity="other" msgid="5523506463832158203">"மேலோட்டப் பார்வையில் %d திரைகள்"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">மேலோட்டப் பார்வையில் %d திரைகள்</item>
+ <item quantity="one">மேலோட்டப் பார்வையில் 1 திரை</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"திற"</string>
<string name="phone_label" msgid="2320074140205331708">"ஃபோனைத் திற"</string>
<string name="camera_label" msgid="7261107956054836961">"கேமராவைத் திற"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"உள்ளீட்டு முறையை மாற்றும் பொத்தான்."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"மொபைல் ஹாட்ஸ்பாட் இயக்கப்பட்டது."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"திரையை அனுப்புதல் நிறுத்தப்பட்டது."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"திரை பிரகாசம்"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G தரவு முடக்கப்பட்டது"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G தரவு முடக்கப்பட்டது"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"செல்லுலார் தரவு முடக்கப்பட்டது"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"தரவு இணைப்பு முடக்கப்பட்டது"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"அமைத்த வரம்பை மீறிவிட்டதால், சாதனம் தரவு இணைப்பை முடக்கியது.\n\nஇதை மீண்டும் இயக்கினால், மொபைல் நிறுவனம் விதிக்கும் கட்டணங்கள் பொருந்தலாம்."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"தரவு இணைப்பை இயக்கு"</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="4651001290947318931">"செல்லுலார் தரவு இடைநிறுத்தப்பட்டது"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"தரவு இடைநிறுத்தப்பட்டது"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"அமைக்கப்பட்ட தரவின் வரம்பை அடைந்துவிட்டதால், இந்தச் சுழற்சியின் மீதமுள்ள நாட்களுக்கான தரவுப் பயன்பாட்டைச் சாதனம் இடைநிறுத்தியுள்ளது.\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">"வைஃபை இணைக்கப்பட்டது"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS ஐத் தேடுகிறது"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ஐ மறைக்கவா?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"அடுத்த முறை அமைப்புகளில் மீண்டும் இயக்கும்போது, இது மீண்டும் தோன்றும்."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"மறை"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g>, ஒலியளவு செய்தியாகச் செயல்பட விரும்புகிறது."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"அனுமதி"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"நிராகரி"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 595a7f6..97ea24c 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"అవలోకనంలో 1 స్క్రీన్ ఉంది"</item>
- <item quantity="other" msgid="5523506463832158203">"అవలోకనంలో %d స్క్రీన్లు ఉన్నాయి"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">స్థూలదృష్టిలో %d స్క్రీన్లు ఉన్నాయి</item>
+ <item quantity="one">స్థూలదృష్టిలో 1 స్క్రీన్ ఉంది</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"అన్లాక్ చేయి"</string>
<string name="phone_label" msgid="2320074140205331708">"ఫోన్ను తెరువు"</string>
<string name="camera_label" msgid="7261107956054836961">"కెమెరాను తెరువు"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ఇన్పుట్ పద్ధతి మార్చే బటన్."</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"మొబైల్ హాట్స్పాట్ ఆన్ చేయబడింది."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"స్క్రీన్ ప్రసారం ఆపివేయబడింది."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ప్రదర్శన ప్రకాశం"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G డేటా ఆఫ్లో ఉంది"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G డేటా ఆఫ్లో ఉంది"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"సెల్యూలార్ డేటా ఆఫ్లో ఉంది"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"డేటా ఆఫ్లో ఉంది"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"మీ పరికరం మీరు సెట్ చేసిన పరిమితిని చేరుకున్నందున డేటాను ఆఫ్ చేసింది.\n\nదీన్ని తిరిగి ఆన్ చేయడం వలన మీ క్యారియర్ను బట్టి ఛార్జీలు పడవచ్చు."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"డేటాను ఆన్ చేయి"</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="4651001290947318931">"సెల్యులార్ డేటా పాజ్ చేయబడింది"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"డేటా పాజ్ చేయబడింది"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"మీ సెట్ చేయబడిన డేటా పరిమితిని చేరుకున్నందున పరికరం ఈ సైకిల్లో మిగిలిన భాగానికి డేటా వినియోగాన్ని పాజ్ చేసింది.\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS కోసం శోధిస్తోంది"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ని దాచాలా?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"మీరు సెట్టింగ్ల్లో దీన్ని ఆన్ చేసిన తదుపరిసారి ఇది కనిపిస్తుంది."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"దాచు"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్గా ఉండాలనుకుంటోంది."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"అనుమతించు"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"తిరస్కరించు"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 9bc4483..286d390 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"1 หน้าจอในภาพรวม"</item>
- <item quantity="other" msgid="5523506463832158203">"%d หน้าจอในภาพรวม"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d หน้าจอในภาพรวม</item>
+ <item quantity="one">1 หน้าจอในภาพรวม</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"ปลดล็อก"</string>
<string name="phone_label" msgid="2320074140205331708">"เปิดโทรศัพท์"</string>
<string name="camera_label" msgid="7261107956054836961">"เปิดกล้อง"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"เปิดฮอตสปอตเคลื่อนที่แล้ว"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"หยุดการส่งหน้าจอแล้ว"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ความสว่างของหน้าจอ"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"ข้อมูล 2G-3G ปิดอยู่"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"ข้อมูล 4G ปิดอยู่"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"ข้อมูลมือถือปิดอยู่"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ข้อมูลปิดอยู่"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"อุปกรณ์ของคุณปิดการใช้ข้อมูลเนื่องจากถึงขีดจำกัดที่คุณตั้งค่าไว้\n\nผู้ให้บริการอาจเรียกเก็บเงินหากเปิดใช้อีกครั้ง"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"เปิดใช้ข้อมูล"</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="4651001290947318931">"หยุดการใช้ข้อมูลมือถือชั่วคราวแล้ว"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"หยุดการใช้ข้อมูลชั่วคราวแล้ว"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"เนื่องจากใช้งานข้อมูลถึงขีดจำกัดที่กำหนดไว้แล้ว อุปกรณ์จึงหยุดการใช้งานข้อมูลไว้ชั่วคราวตลอดระยะเวลาที่เหลือของรอบนี้\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">"เชื่อมต่อ WiFi แล้ว"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"กำลังค้นหา GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ซ่อน <xliff:g id="TILE_LABEL">%1$s</xliff:g> ไหม"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"จะปรากฏอีกครั้งเมื่อคุณเปิดใช้ในการตั้งค่าครั้งถัดไป"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"ซ่อน"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ต้องการเป็่นช่องโต้ตอบระดับเสียง"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"อนุญาต"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"ปฏิเสธ"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index e1c0fcd..95d16d0 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Impormasyon ng app"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Lumalabas dito ang iyong kamakailang screen"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Huwag pansinin ang kamakailang apps"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 screen sa Overview"</item>
- <item quantity="other" msgid="5523506463832158203">"%d (na) screen sa Overview"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d screen sa Pangkalahatang-ideya</item>
+ <item quantity="other">%d na screen sa Pangkalahatang-ideya</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Walang mga notification"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"i-unlock"</string>
<string name="phone_label" msgid="2320074140205331708">"buksan ang telepono"</string>
<string name="camera_label" msgid="7261107956054836961">"buksan ang camera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Button ng zoom ng pagiging tugma."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Mag-zoom nang mas maliit sa mas malaking screen."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Nakakonekta ang Bluetooth."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Na-on ang mobile hotspot."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Itinigil ang pagka-cast sa screen."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Liwanag ng display"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Naka-off ang 2G-3G data"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Naka-off ang 4G data"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Naka-off ang cellular data"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Naka-off ang data"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Ini-off ng device mo ang data dahil naabot na nito ang limitasyong iyong itinakda.\n\nAng muling pag-o-on dito ay maaaring humantong sa mga singiling magmumula sa iyong carrier."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"I-on ang data"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Naka-pause ang 2G-3G data"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Naka-pause ang 4G data"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Naka-pause ang cellular data"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Naka-pause ang data"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Dahil naabot ang iyong nakatakdang limitasyon sa data, na-pause ng device ang paggamit ng data para sa nalalabing bahagi ng cycle na ito.\n\nMaaaring makakuha ng mga singilin mula sa iyong carrier ang pagpapatuloy."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Ipagpatuloy"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Walang koneksyon sa Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"nakakonekta ang Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Naghahanap ng GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Itago ang <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Lalabas itong muli sa susunod na pagkakataon na i-on mo ito sa mga setting."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Itago"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Gusto ng <xliff:g id="APP_NAME">%1$s</xliff:g> na maging volume dialog."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Payagan"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tanggihan"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 29a5879..10ca6fe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Uygulama bilgileri"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Son ekranlarınız burada görünür"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Son uygulamaları kapat"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"Genel Bakış\'ta 1 ekran"</item>
- <item quantity="other" msgid="5523506463832158203">"Genel Bakış\'ta %d ekran"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">Genel Bakış\'ta %d ekran</item>
+ <item quantity="one">Genel Bakış\'ta 1 ekran</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildirim yok"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"kilidi aç"</string>
<string name="phone_label" msgid="2320074140205331708">"telefonu aç"</string>
<string name="camera_label" msgid="7261107956054836961">"kamerayı aç"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Giriş yöntemini değiştirme düğmesi."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyumluluk zum düğmesi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha büyük ekrana daha küçük yakınlaştır."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth bağlandı."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobil hotspot açıldı."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ekran yayını durduruldu."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekran parlaklığı"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G veri kullanımı kapalı"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G veri kullanımı kapalı"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Hücresel veri kapalı"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Veri kullanımı kapalı"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Ayarladığınız sınıra erişildiğinden cihazınız veri kullanımını kapattı.\n\nVeri kullanımını tekrar açmanız operatörünüzün ek ödemeler almasına neden olabilir."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Veri kullanımını aç"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G veri kullanımı duraklatıldı"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G veri kullanımı duraklatıldı"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Hücresel veri kullanımı duraklatıldı"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Veri kullanımı duraklatıldı"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ayarlanmış olan veri sınırınıza ulaşıldığından, bu dönemin kalan süresi için cihazda veri kullanımı duraklatıldı.\n\nVeri kullanımını devam ettirmek, operatörünüzün sizden ödeme almasına neden olabilir."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Devam ettir"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"İnternet bağlantısı yok"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Kablosuz bağlandı"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> gizlensin mi?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Ayarlardan etkinleştirdiğiniz bir sonraki sefer tekrar görünür."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Gizle"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olmak istiyor."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"İzin ver"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Reddet"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinali geri yüklemek için dokunun."</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3058b94..ef6c28d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -25,10 +25,12 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"Показано 1 екран"</item>
- <item quantity="other" msgid="5523506463832158203">"Показано екранів: %d"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">На панелі огляду %d екран</item>
+ <item quantity="few">На панелі огляду %d екрани</item>
+ <item quantity="many">На панелі огляду %d екранів</item>
+ <item quantity="other">На панелі огляду %d екрана</item>
+ </plurals>
<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>
@@ -88,7 +90,6 @@
<string name="unlock_label" msgid="8779712358041029439">"розблокувати"</string>
<string name="phone_label" msgid="2320074140205331708">"відкрити телефон"</string>
<string name="camera_label" msgid="7261107956054836961">"відкрити камеру"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</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>
@@ -201,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Мобільну точку доступу ввімкнено."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Трансляцію екрана зупинено."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Яскравість дисплея"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Дані 2G–3G вимкнено"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Дані 4G вимкнено"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Мобільні дані вимкнено"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Дані вимкнено"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Пристрій вимкнув передавання даних, оскільки перевищено встановлений вами ліміт.\n\nЯкщо передавання даних знову ввімкнути, оператор може стягувати додаткову плату."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Увімкнути дані"</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="4651001290947318931">"Передавання мобільних даних призупинено"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Передавання даних призупинено"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Пристрій призупинив передавання даних до кінця цього циклу, оскільки ваш ліміт перевищено.\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="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
@@ -369,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сховати <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"З’явиться знову, коли ви ввімкнете його в налаштуваннях."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Сховати"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"Призначити додаток <xliff:g id="APP_NAME">%1$s</xliff:g> регулятором гучності?"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Дозволити"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Відхилити"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 89269ed..ec66ac4 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"مجموعی جائزہ میں 1 اسکرین"</item>
- <item quantity="other" msgid="5523506463832158203">"مجموعی جائزہ میں %d اسکرینز"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">عمومی جائزہ میں %d اسکرینز</item>
+ <item quantity="one">عمومی جائزہ میں 1 اسکرین</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"غیر مقفل کریں"</string>
<string name="phone_label" msgid="2320074140205331708">"فون کھولیں"</string>
<string name="camera_label" msgid="7261107956054836961">"کیمرا کھولیں"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"اندراج کا طریقہ سوئچ کرنے کا بٹن۔"</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>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"موبائل ہاٹ اسپاٹ کو آن کر دیا گیا۔"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"اسکرین کو کاسٹ کرنا بند کر دیا۔"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ڈسپلے کی چمک"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G ڈیٹا آف ہے"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G ڈیٹا آف ہے"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"سیلولر ڈیٹا آف ہے"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"ڈیٹا آف ہے"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"آپ کے آلہ نے ڈیٹا کو آف کر دیا کیونکہ یہ آپ کی متعینہ حد کو پہنچ گیا۔\n\nاسے دوبارہ آن کرنے سے آپ کے کیریئر کی جانب سے چارجز عائد ہو سکتے ہیں۔"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"ڈیٹا آن کریں"</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="4651001290947318931">"سیلولر ڈیٹا موقوف کر دیا گیا"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"ڈیٹا موقوف کر دیا گیا"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"چونکہ آپ کی سیٹ کردہ ڈیٹا کی حد تک پہنچ گیا، لہذا آلہ نے اس سائیکل کے بقیہ حصے کیلئے ڈیٹا کے استعمال کو موقوف کر دیا ہے۔\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="gps_notification_searching_text" msgid="8574247005642736060">"GPS کی تلاش کر رہا ہے"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> کو چھپائیں؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"اگلی بار جب آپ اسے ترتیبات میں آن کریں گے تو یہ ظاہر ہوگی۔"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"چھپائیں"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ بننا چاہتی ہے۔"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"اجازت دیں"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"مسترد کریں"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"اصل کو بحال کرنے کیلئے ٹچ کریں۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index b9941da..439adcf 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Ilova xaqida"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Yaqinda ish-gan ilovalar bu yerda ko‘rinadi"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"So‘nggi dasturlarni tozalash"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"“Umumiy nazar” oynasida 1 ta ekran bor"</item>
- <item quantity="other" msgid="5523506463832158203">"“Umumiy nazar” oynasida %d ta ekran bor"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">Umumiy ma’lumot bo‘limida %d ta ekran bor</item>
+ <item quantity="one">Umumiy ma’lumot bo‘limida 1 ta ekran bor</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Eslatmalar - yo‘q"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Joriy"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Eslatmalar"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"qulfdan chiqarish"</string>
<string name="phone_label" msgid="2320074140205331708">"telefonni ochish"</string>
<string name="camera_label" msgid="7261107956054836961">"kamerani ochish"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Kiritish uslubi tugmasini almashtirish."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Kattalashtirish tugmasi mosligi."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Kattaroq ekran uchun kichikroqni kattalashtirish."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ulandi."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Mobil ulanish nuqtasi yoqildi."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ekranni translatsiya qilish to‘xtadi."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Ekran yorqinligi"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G/3G internet o‘chirib qo‘yildi"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G internet o‘chirib qo‘yildi"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Mobil internet o‘chirib qo‘yildi"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Internet o‘chirib qo‘yildi"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Siz o‘rnatgan chegaraga yetib kelgani tufayli qurilmangizda internet o‘chirib qo‘yildi.\n\nUni qayta yoqishingiz mumkin, biroq buning uchun aloqa operatoringiz qo‘shimcha haq olishi mumkin."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Internetni yoqish"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G internet to‘xtatib qo‘yildi"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobil internetdan foydalanish to‘xtatib qo‘yildi"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Internetdan foydalanish to‘xtatib qo‘yildi"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Siz o‘rnatgan mobil internet chekloviga yetgani bois joriy hisob-kitob davrining qolgan muddati uchun mobil internetdan foydalanish vaqtinchalik to‘xtatib qo‘yildi.\n\nAgar internetdan foydalanishni davom ettirsangiz, buning uchun uyali aloqa operatoringiz ortiqcha haq talab qilishi mumkin."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Davom etish"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Internetga ulanmagan"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ulandi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS qidirilmoqda"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> berkitilsinmi?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Keyingi safar sozlamalardan yoqilgan paydo bo‘ladi."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Berkitish"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqarmoqchi."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Ruxsat berish"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rad etish"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 8f0c1fc..759a4fb 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Thông tin về ứng dụng"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Màn hình gần đây của bạn sẽ xuất hiện tại đây"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Loại bỏ các ứng dụng gần đây"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 màn hình trong Tổng quan"</item>
- <item quantity="other" msgid="5523506463832158203">"%d màn hình trong Tổng quan"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">%d màn hình trong Tổng quan</item>
+ <item quantity="one">1 màn hình trong Tổng quan</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Không có thông báo nào"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"mở khóa"</string>
<string name="phone_label" msgid="2320074140205331708">"mở điện thoại"</string>
<string name="camera_label" msgid="7261107956054836961">"mở máy ảnh"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Nút thu phóng khả năng tương thích."</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Thu phóng màn hình lớn hơn hoặc nhỏ hơn."</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Đã kết nối bluetooth."</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Đã bật điểm phát sóng di động."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Đã ngừng truyền màn hình."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Độ sáng màn hình"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Dữ liệu 2G-3G bị tắt"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Dữ liệu 4G bị tắt"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Dữ liệu di động bị tắt"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Dữ liệu bị tắt"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Thiết bị của bạn đã tắt dữ liệu do đã đạt đến giới hạn bạn đã đặt.\n\nViệc bật lại dữ liệu có thể dẫn tới các khoản phí từ nhà cung cấp dịch vụ của bạn."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Bật dữ liệu"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Đã tạm dừng dữ liệu 2G-3G"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Đã tạm dừng dữ liệu 4G"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Đã tạm dừng dữ liệu di động"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Đã tạm dừng dữ liệu"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Vì bạn đã đạt tới giới hạn dữ liệu thiết lập nên thiết bị đã tạm dừng sử dụng dữ liệu cho phần còn lại của chu kỳ này.\n\nTiếp tục có thể dẫn tới nhà cung cấp dịch vụ của bạn sẽ tính phí."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Tiếp tục"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ko có k.nối Internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Đã kết nối Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ẩn <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Thông báo này sẽ xuất hiện lại vào lần tiếp theo bạn bật thông báo trong cài đặt."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ẩn"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"<xliff:g id="APP_NAME">%1$s</xliff:g> muốn trở thành hộp thoại khối lượng."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Cho phép"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Từ chối"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 678654b2..1c39be4 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"概览中有 1 个屏幕"</item>
- <item quantity="other" msgid="5523506463832158203">"概览中有 %d 个屏幕"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">概览中有 %d 个屏幕</item>
+ <item quantity="one">概览中有 1 个屏幕</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"解锁"</string>
<string name="phone_label" msgid="2320074140205331708">"打开电话"</string>
<string name="camera_label" msgid="7261107956054836961">"打开相机"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"移动热点已开启。"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"屏幕投射已停止。"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"屏幕亮度"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G数据网络已关闭"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G数据网络已关闭"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"移动数据网络已关闭"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"数据网络已关闭"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"由于数据流量已达到您所设置的上限,因此您的设备已关闭数据网络。\n\n如果重新开启数据网络,那么您的运营商可能会向您收取相应费用。"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"开启数据网络"</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="4651001290947318931">"移动数据网络已暂停使用"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"数据网络已暂停使用"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由于使用的数据流量已达到您所设置的上限,因此您的设备已暂停在此周期的剩余时间内使用数据流量。\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">"已连接到WLAN网络"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"要隐藏“<xliff:g id="TILE_LABEL">%1$s</xliff:g>”吗?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"下次在设置中将其开启后,此快捷设置条目将会重新显示。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"隐藏"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”请求用作音量控制对话框。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"允许"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒绝"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"触摸即可恢复原始设置。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e35e632..a4f4f45 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"概覽中有 1 個畫面"</item>
- <item quantity="other" msgid="5523506463832158203">"概覽中有 %d 個畫面"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">概覽中有 %d 個畫面</item>
+ <item quantity="one">概覽中有 1 個畫面</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"解鎖"</string>
<string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
<string name="camera_label" msgid="7261107956054836961">"開啟相機"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"流動熱點已開啟。"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"已停止投放螢幕。"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"顯示光暗度"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G 數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G 數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"流動數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"數據流量已達到您所設定的上限,因此裝置關閉了數據連線。\n\n若重新開啟數據連線,流動網絡供應商可能會向您收費。"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"開啟數據連線"</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="4651001290947318931">"已暫停流動數據"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"已暫停使用數據"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由於您已達到設定的數據用量上限,裝置已暫停使用數據,直到週期結束。\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="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏 <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"下一次您在設定開啟它時,它將再次出現。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"隱藏"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」想成為音量對話框。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"允許"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ac8135b..b38991d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -25,10 +25,10 @@
<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">
- <item quantity="one" msgid="3969335317929254918">"總覽中有 1 個畫面"</item>
- <item quantity="other" msgid="5523506463832158203">"總覽中有 %d 個畫面"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="other">總覽中有 %d 個畫面</item>
+ <item quantity="one">總覽中有 1 個畫面</item>
+ </plurals>
<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>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"解除鎖定"</string>
<string name="phone_label" msgid="2320074140205331708">"開啟電話"</string>
<string name="camera_label" msgid="7261107956054836961">"開啟攝影機"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</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>
@@ -203,12 +202,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"可攜式無線基地台已開啟。"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"已停止投放螢幕。"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"螢幕亮度"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"2G-3G 數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"4G 數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"行動數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"數據連線已關閉"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"數據流量已達您所設定的上限,因此裝置關閉了數據連線。\n\n如果重新開啟數據連線,行動通訊業者可能會向您收費。"</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"開啟數據連線"</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="4651001290947318931">"已暫停行動數據連線"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"已暫停數據連線"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"由於數據用量已達設定上限,裝置在這個週期的剩餘時間將暫停使用數據連線。\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="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
@@ -371,4 +370,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"只要在設定頁面中重新啟用,就能再次看到快捷設定選項。"</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"隱藏"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」要求成為預設的音量控制對話方塊。"</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"允許"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸這裡即可恢復原始設定。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a91d76c..7f3ac02 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -25,10 +25,10 @@
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Ulwazi lwensiza"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Izikrini zakho zakamuva zivela lapha"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Susa izinhlelo zokusebenza zakamumva"</string>
- <plurals name="status_bar_accessibility_recent_apps">
- <item quantity="one" msgid="3969335317929254918">"1 isikrini esiku-Buka konke"</item>
- <item quantity="other" msgid="5523506463832158203">"%d wezikrini eziku-Buka konke"</item>
- </plurals>
+ <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+ <item quantity="one">%d izikrini eziku-Buka konke</item>
+ <item quantity="other">%d izikrini eziku-Buka konke</item>
+ </plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Azikho izaziso"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Okuqhubekayo"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Izaziso"</string>
@@ -88,7 +88,6 @@
<string name="unlock_label" msgid="8779712358041029439">"vula"</string>
<string name="phone_label" msgid="2320074140205331708">"vula ifoni"</string>
<string name="camera_label" msgid="7261107956054836961">"vula ikhamera"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
<string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Inkinobho evumelekile yokusondeza"</string>
<string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Sondeza kancane esikrinini esikhudlwana"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth ixhunyiwe"</string>
@@ -201,12 +200,12 @@
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"I-hotspot ivuliwe."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Ukusakaza kwesikrini kumisiwe."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Bonisa ukukhanya"</string>
- <string name="data_usage_disabled_dialog_3g_title" msgid="2626865386971800302">"Idatha ye-2G-3G ivaliwe"</string>
- <string name="data_usage_disabled_dialog_4g_title" msgid="4629078114195977196">"Idatha ye-4G ivaliwe"</string>
- <string name="data_usage_disabled_dialog_mobile_title" msgid="5793456071535876132">"Idatha yeselula ivaliwe"</string>
- <string name="data_usage_disabled_dialog_title" msgid="8723412000355709802">"Idatha ivaliwe"</string>
- <string name="data_usage_disabled_dialog" msgid="6468718338038876604">"Idivayisi yakho ivale idatha ngoba ifinyelele umkhawulo owubekile.\n\nUkuyivula futhi kungaholela ezindlekweni kusuka kunkampani yakho yenethiwekhi."</string>
- <string name="data_usage_disabled_dialog_enable" msgid="5538068036107372895">"Vula idatha"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G idatha imisiwe"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G idatha imisiwe"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Idatha yeselula imisiwe"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Idatha imisiwe"</string>
+ <string name="data_usage_disabled_dialog" msgid="8453242888903772524">"Ngoba umkhawulo wakho wedatha osethiwe ufinyelelwe, idivayisi imise kancane ukusetshenziswa kwedatha ngesikhumbuzi salo mjikelezo.\n\nUkuqhuba futhi kungaholela kuzindleko kusuka kwinkampani yakho yenethiwekhi."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Qalisa kabusha"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Alukho uxhumano lwe-Inthanethi"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"I-Wi-Fi ixhunyiwe"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Isesha i-GPS"</string>
@@ -369,4 +368,9 @@
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fihla i-<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Izovela ngesikhathi esilandelayo uma uvule lesi silungiselelo."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Fihla"</string>
+ <string name="volumeui_prompt_message" msgid="918680947433389110">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ifuna ukuba yingxoxo yevolumu."</string>
+ <string name="volumeui_prompt_allow" msgid="7954396902482228786">"Vumela"</string>
+ <string name="volumeui_prompt_deny" msgid="5720663643411696731">"Phika"</string>
+ <string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string>
+ <string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8a73fca..2e9e9f7 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -118,7 +118,7 @@
<!-- The default tiles to display in QuickSettings -->
<string name="quick_settings_tiles_default" translatable="false">
- wifi,bt,inversion,cell,airplane,rotation,flashlight,location,cast,hotspot
+ wifi,bt,inversion,dnd,cell,airplane,rotation,flashlight,location,cast,hotspot
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index aa53a3e..3fc75d2 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -40,6 +40,7 @@
<item type="id" name="notification_power"/>
<item type="id" name="notification_screenshot"/>
<item type="id" name="notification_hidden"/>
+ <item type="id" name="notification_volumeui"/>
<!-- Whether the icon is from a notification for which targetSdk < L -->
<item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6afca8a..1b1b525 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -217,8 +217,6 @@
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="camera_label">open camera</string>
- <!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_ime_switch_button">Switch input method button.</string>
<!-- Content description of the compatibility zoom button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_compatibility_zoom_button">Compatibility zoom button.</string>
@@ -432,6 +430,16 @@
<string name="accessibility_quick_settings_airplane_changed_off">Airplane mode turned off.</string>
<!-- Announcement made when the airplane mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_airplane_changed_on">Airplane mode turned on.</string>
+ <!-- Content description of the do not disturb tile in quick settings when on in priority (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_dnd_priority_on">Do not disturb on, priority only.</string>
+ <!-- Content description of the do not disturb tile in quick settings when on in none (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_dnd_none_on">Do not disturb on, no interruptions.</string>
+ <!-- Content description of the do not disturb tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_dnd_off">Do not disturb off.</string>
+ <!-- Announcement made when do not disturb changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_dnd_changed_off">Do not disturb turned off.</string>
+ <!-- Announcement made when do not disturb changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_dnd_changed_on">Do not disturb turned on.</string>
<!-- Content description of the bluetooth tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_quick_settings_bluetooth_off">Bluetooth off.</string>
<!-- Content description of the bluetooth tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -483,17 +491,17 @@
<string name="accessibility_brightness">Display brightness</string>
<!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_3g_title">2G-3G data is off</string>
+ <string name="data_usage_disabled_dialog_3g_title">2G-3G data is paused</string>
<!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_4g_title">4G data is off</string>
+ <string name="data_usage_disabled_dialog_4g_title">4G data is paused</string>
<!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_mobile_title">Cellular data is off</string>
+ <string name="data_usage_disabled_dialog_mobile_title">Cellular data is paused</string>
<!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_title">Data is off</string>
+ <string name="data_usage_disabled_dialog_title">Data is paused</string>
<!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
- <string name="data_usage_disabled_dialog">Your device turned off data because it reached the limit you set.\n\nTurning it back on may lead to charges from your carrier.</string>
+ <string name="data_usage_disabled_dialog">Because your set data limit was reached, the device has paused data usage for the remainder of this cycle.\n\nResuming may lead to charges from your carrier.</string>
<!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
- <string name="data_usage_disabled_dialog_enable">Turn on data</string>
+ <string name="data_usage_disabled_dialog_enable">Resume</string>
<!-- Text to display underneath the graphical signal strength meter when
no connection is available. [CHAR LIMIT=20] -->
@@ -556,6 +564,12 @@
<!-- QuickSettings: Airplane mode [CHAR LIMIT=NONE] -->
<string name="quick_settings_airplane_mode_label">Airplane mode</string>
+ <!-- QuickSettings: Do not disturb [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_dnd_label">Do not disturb</string>
+ <!-- QuickSettings: Do not disturb - Priority only [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_dnd_priority_label">Priority only</string>
+ <!-- QuickSettings: Do not disturb - No interruptions [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_dnd_none_label">No interruptions</string>
<!-- QuickSettings: Bluetooth [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_label">Bluetooth</string>
<!-- QuickSettings: Bluetooth (Multiple) [CHAR LIMIT=NONE] -->
@@ -932,4 +946,19 @@
<!-- Hide quick settings tile confirmation button -->
<string name="quick_settings_reset_confirmation_button">Hide</string>
+
+ <!-- VolumeUI activation dialog: warning message -->
+ <string name="volumeui_prompt_message"><xliff:g id="app_name" example="Volume Prototype 1">%1$s</xliff:g> wants to be the volume dialog.</string>
+
+ <!-- VolumeUI activation dialog: allow button label -->
+ <string name="volumeui_prompt_allow">Allow</string>
+
+ <!-- VolumeUI activation dialog: deny button label -->
+ <string name="volumeui_prompt_deny">Deny</string>
+
+ <!-- VolumeUI restoration notification: title -->
+ <string name="volumeui_notification_title"><xliff:g id="app_name" example="Volume Prototype 1">%1$s</xliff:g> is the volume dialog</string>
+
+ <!-- VolumeUI restoration notification: text -->
+ <string name="volumeui_notification_text">Touch to restore the original.</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f3d214f..1cf0129 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1300,6 +1300,8 @@
@Override
public void run() {
try {
+ mStatusBarKeyguardViewManager.keyguardGoingAway();
+
// Don't actually hide the Keyguard at the moment, wait for window
// manager until it tells us it's safe to do so with
// startKeyguardExitAnimation.
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 25bab17..c23f45d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -114,7 +114,9 @@
@Override
protected void onDestroy() {
super.onDestroy();
- mDialog.dismiss();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
}
@Override
@@ -128,7 +130,9 @@
Log.e(TAG, "Error granting projection permission", e);
setResult(RESULT_CANCELED);
} finally {
- mDialog.dismiss();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
finish();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 4dacacf..7f944f0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -253,12 +253,6 @@
@Override
public void onStateChanged(QSTile.State state) {
int visibility = state.visible ? VISIBLE : GONE;
- if (state.visible && !mGridContentVisible) {
-
- // We don't want to show it if the content is hidden,
- // then we just set it to invisible, to ensure that it gets visible again
- visibility = INVISIBLE;
- }
setTileVisibility(r.tileView, visibility);
r.tileView.onStateChanged(state);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
new file mode 100644
index 0000000..79600f5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.volume.ZenModePanel;
+
+/** Quick settings tile: Do not disturb **/
+public class DndTile extends QSTile<QSTile.BooleanState> {
+ private static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
+
+ private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
+ private static final String EXTRA_VISIBLE = "visible";
+ private static final String PREF_KEY_VISIBLE = "DndTileVisible";
+
+ private final ZenModeController mController;
+ private final DndDetailAdapter mDetailAdapter;
+
+ private boolean mListening;
+ private boolean mVisible;
+ private boolean mShowingDetail;
+
+ public DndTile(Host host) {
+ super(host);
+ mController = host.getZenModeController();
+ mDetailAdapter = new DndDetailAdapter();
+ mVisible = getSharedPrefs(mContext).getBoolean(PREF_KEY_VISIBLE, false);
+ mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
+ }
+
+ public static void setVisible(Context context, boolean visible) {
+ context.sendBroadcast(new Intent(DndTile.ACTION_SET_VISIBLE)
+ .putExtra(DndTile.EXTRA_VISIBLE, visible));
+ }
+
+ public static boolean isVisible(Context context) {
+ return getSharedPrefs(context).getBoolean(PREF_KEY_VISIBLE, false);
+ }
+
+ @Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
+ protected BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void handleClick() {
+ if (mState.value) {
+ mController.setZen(Global.ZEN_MODE_OFF);
+ } else {
+ mController.setZen(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ showDetail(true);
+ }
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
+ state.value = zen != Global.ZEN_MODE_OFF;
+ state.visible = mVisible;
+ switch (zen) {
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
+ state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_dnd_priority_on);
+ break;
+ case Global.ZEN_MODE_NO_INTERRUPTIONS:
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
+ state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_dnd_none_on);
+ break;
+ default:
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_off);
+ state.label = mContext.getString(R.string.quick_settings_dnd_label);
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_dnd_off);
+ break;
+ }
+ if (mShowingDetail && !state.value) {
+ showDetail(false);
+ }
+ }
+
+ @Override
+ protected String composeChangeAnnouncement() {
+ if (mState.value) {
+ return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
+ } else {
+ return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
+ }
+ }
+
+ @Override
+ public void setListening(boolean listening) {
+ if (mListening == listening) return;
+ mListening = listening;
+ if (mListening) {
+ mController.addCallback(mZenCallback);
+ } else {
+ mController.removeCallback(mZenCallback);
+ }
+ }
+
+ private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
+ public void onZenChanged(int zen) {
+ refreshState(zen);
+ }
+ };
+
+ private static SharedPreferences getSharedPrefs(Context context) {
+ return context.getSharedPreferences(context.getPackageName(), 0);
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mVisible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
+ getSharedPrefs(mContext).edit().putBoolean(PREF_KEY_VISIBLE, mVisible).commit();
+ refreshState();
+ }
+ };
+
+ private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_dnd_label;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return mState.value;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return ZEN_SETTINGS;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ if (!state) {
+ mController.setZen(Global.ZEN_MODE_OFF);
+ showDetail(false);
+ }
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
+ : (ZenModePanel) LayoutInflater.from(context).inflate(
+ R.layout.zen_mode_panel, parent, false);
+ if (convertView == null) {
+ zmp.init(mController);
+ zmp.setEmbedded(true);
+ zmp.addOnAttachStateChangeListener(this);
+ }
+ return zmp;
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mShowingDetail = true;
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mShowingDetail = false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b1ac733..e0b4c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -193,8 +193,7 @@
}
// Start loading tasks according to the load plan
- ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
- if (stacks.size() == 0) {
+ if (!plan.hasTasks()) {
loader.preloadTasks(plan, mConfig.launchedFromHome);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -203,11 +202,11 @@
loadOpts.numVisibleTaskThumbnails = mConfig.launchedNumVisibleThumbnails;
loader.loadTasks(this, plan, loadOpts);
- boolean hasTasks = plan.hasTasks();
- if (hasTasks) {
+ ArrayList<TaskStack> stacks = plan.getAllTaskStacks();
+ mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
+ if (!mConfig.launchedWithNoRecentTasks) {
mRecentsView.setTaskStacks(stacks);
}
- mConfig.launchedWithNoRecentTasks = !hasTasks;
// Create the home intent runnable
Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 2318319..21975b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -879,7 +879,7 @@
// Start the focus animation when alt-tabbing
if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged) {
- TaskView tv = taskViews.get(mFocusedTaskIndex);
+ TaskView tv = getChildViewForTask(mStack.getTasks().get(mFocusedTaskIndex));
if (tv != null) {
tv.setFocusedTask(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index b827acc..81e960a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -32,12 +32,10 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.widget.FrameLayout;
@@ -104,11 +102,10 @@
});
// Load the dismiss resources
- Resources res = context.getResources();
- mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light);
- mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark);
+ mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
+ mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
mDismissContentDescription =
- res.getString(R.string.accessibility_recents_item_will_be_dismissed);
+ context.getString(R.string.accessibility_recents_item_will_be_dismissed);
// Configure the highlight paint
if (sHighlightPaint == null) {
@@ -283,23 +280,26 @@
}
if (focused) {
+ int currentColor = mBackgroundColor;
int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
int[][] states = new int[][] {
+ new int[] {},
new int[] { android.R.attr.state_enabled },
new int[] { android.R.attr.state_pressed }
};
int[] newStates = new int[]{
+ 0,
android.R.attr.state_enabled,
android.R.attr.state_pressed
};
int[] colors = new int[] {
+ currentColor,
secondaryColor,
secondaryColor
};
mBackground.setColor(new ColorStateList(states, colors));
mBackground.setState(newStates);
// Pulse the background color
- int currentColor = mBackgroundColor;
int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
currentColor, lightPrimaryColor);
@@ -326,7 +326,7 @@
mFocusAnimator = new AnimatorSet();
mFocusAnimator.playTogether(backgroundColor, translation);
- mFocusAnimator.setStartDelay(750);
+ mFocusAnimator.setStartDelay(150);
mFocusAnimator.setDuration(750);
mFocusAnimator.start();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 0b1b883..8f88e73d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -19,6 +19,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.util.Pair;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -57,6 +58,9 @@
private static final int MSG_NOTIFICATION_LIGHT_OFF = 16 << MSG_SHIFT;
private static final int MSG_NOTIFICATION_LIGHT_PULSE = 17 << MSG_SHIFT;
private static final int MSG_SHOW_SCREEN_PIN_REQUEST = 18 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_PENDING = 19 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_CANCELLED = 20 << MSG_SHIFT;
+ private static final int MSG_APP_TRANSITION_STARTING = 21 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -99,6 +103,9 @@
public void notificationLightOff();
public void notificationLightPulse(int argb, int onMillis, int offMillis);
public void showScreenPinningRequest();
+ public void appTransitionPending();
+ public void appTransitionCancelled();
+ public void appTransitionStarting(long startTime, long duration);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -246,6 +253,28 @@
}
}
+ public void appTransitionPending() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
+ mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ }
+ }
+
+ public void appTransitionCancelled() {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
+ mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ }
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
+ mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration))
+ .sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -328,6 +357,16 @@
case MSG_SHOW_SCREEN_PIN_REQUEST:
mCallbacks.showScreenPinningRequest();
break;
+ case MSG_APP_TRANSITION_PENDING:
+ mCallbacks.appTransitionPending();
+ break;
+ case MSG_APP_TRANSITION_CANCELLED:
+ mCallbacks.appTransitionCancelled();
+ break;
+ case MSG_APP_TRANSITION_STARTING:
+ Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
+ mCallbacks.appTransitionStarting(data.first, data.second);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 0fc46e9..01aa8d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -44,7 +44,7 @@
}
private void draw(Canvas canvas, Drawable drawable) {
- if (drawable != null) {
+ if (drawable != null && mActualHeight > mClipTopAmount) {
drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
drawable.draw(canvas);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
index aea9ec6..69a4932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
@@ -279,4 +279,14 @@
}
return sb.append('}').toString();
}
+
+ public ComponentName getComponent() {
+ return getComponentNameFromSetting();
+ }
+
+ public void setComponent(ComponentName component) {
+ final String setting = component == null ? null : component.flattenToShortString();
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ mSettingKey, setting, UserHandle.USER_CURRENT);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ece69d3..8aafe52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -101,7 +101,6 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
@@ -115,7 +114,6 @@
import com.android.systemui.DemoMode;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
-import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -138,7 +136,6 @@
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.SpeedBumpView;
-import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -3118,6 +3115,8 @@
mLaunchTransitionFadingAway = false;
}
});
+ mIconController.appTransitionStarting(SystemClock.uptimeMillis(),
+ StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
}
};
if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -3185,16 +3184,31 @@
}
/**
+ * Notifies the status bar that Keyguard is going away very soon.
+ */
+ public void keyguardGoingAway() {
+
+ // Treat Keyguard exit animation as an app transition to achieve nice transition for status
+ // bar.
+ mIconController.appTransitionPending();
+ }
+
+ /**
* Notifies the status bar the Keyguard is fading away with the specified timings.
*
- * @param delay the animation delay in miliseconds
+ * @param startTime the start time of the animations in uptime millis
+ * @param delay the precalculated animation delay in miliseconds
* @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
- public void setKeyguardFadingAway(long delay, long fadeoutDuration) {
+ public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) {
mKeyguardFadingAway = true;
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
+ mIconController.appTransitionStarting(
+ startTime + fadeoutDuration
+ - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
+ StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
disable(mDisabledUnmodified, true /* animate */);
}
@@ -3210,8 +3224,9 @@
}
private void updatePublicMode() {
- setLockscreenPublicMode(mStatusBarKeyguardViewManager.isShowing()
- && mStatusBarKeyguardViewManager.isSecure(mCurrentUserId));
+ setLockscreenPublicMode(
+ mStatusBarKeyguardViewManager.isShowing() && mStatusBarKeyguardViewManager
+ .isSecure(mCurrentUserId));
}
private void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
@@ -3638,6 +3653,31 @@
}
}
+ @Override
+ public void appTransitionPending() {
+
+ // Use own timings when Keyguard is going away, see keyguardGoingAway and
+ // setKeyguardFadingAway
+ if (!mKeyguardFadingAway) {
+ mIconController.appTransitionPending();
+ }
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ mIconController.appTransitionCancelled();
+ }
+
+ @Override
+ public void appTransitionStarting(long startTime, long duration) {
+
+ // Use own timings when Keyguard is going away, see keyguardGoingAway and
+ // setKeyguardFadingAway
+ if (!mKeyguardFadingAway) {
+ mIconController.appTransitionStarting(startTime, duration);
+ }
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index e8a000c..5da8457 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.R;
+import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -198,7 +199,11 @@
int volumeIconId = 0;
String volumeDescription = null;
- if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ if (DndTile.isVisible(mContext)) {
+ zenVisible = mZen != Global.ZEN_MODE_OFF;
+ zenIconId = R.drawable.stat_sys_dnd;
+ zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
+ } else if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
zenVisible = true;
zenIconId = R.drawable.stat_sys_zen_none;
zenDescription = mContext.getString(R.string.zen_no_interruptions);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 45a1386..954eb10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -41,6 +41,7 @@
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.WifiTile;
+import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
@@ -256,6 +257,7 @@
else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
else if (tileSpec.equals("cell")) return new CellularTile(this);
else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
+ else if (tileSpec.equals("dnd")) return new DndTile(this);
else if (tileSpec.equals("rotation")) return new RotationLockTile(this);
else if (tileSpec.equals("flashlight")) return new FlashlightTile(this);
else if (tileSpec.equals("location")) return new LocationTile(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 5622993..3bdf94a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,11 +16,15 @@
package com.android.systemui.statusbar.phone;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
@@ -48,9 +52,12 @@
*/
public class StatusBarIconController {
+ public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+
private Context mContext;
private PhoneStatusBar mPhoneStatusBar;
private Interpolator mLinearOutSlowIn;
+ private Interpolator mFastOutSlowIn;
private DemoStatusIcons mDemoStatusIcons;
private NotificationColorUtil mNotificationColorUtil;
@@ -69,6 +76,23 @@
private int mIconTint = Color.WHITE;
+ private boolean mTransitionPending;
+ private boolean mTintChangePending;
+ private int mPendingIconTint;
+ private ValueAnimator mTintAnimator;
+
+ private final Handler mHandler;
+ private boolean mTransitionDeferring;
+ private long mTransitionDeferringStartTime;
+ private long mTransitionDeferringDuration;
+
+ private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mTransitionDeferring = false;
+ }
+ };
+
public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
PhoneStatusBar phoneStatusBar) {
mContext = context;
@@ -86,6 +110,9 @@
mClock = (TextView) statusBar.findViewById(R.id.clock);
mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
+ mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
+ android.R.interpolator.fast_out_slow_in);
+ mHandler = new Handler();
updateResources();
}
@@ -268,10 +295,49 @@
}
public void setIconTint(int tint) {
+ if (mTransitionPending) {
+ deferIconTintChange(tint);
+ } else if (mTransitionDeferring) {
+ animateIconTint(tint,
+ Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
+ mTransitionDeferringDuration);
+ } else {
+ animateIconTint(tint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ }
+
+ private void animateIconTint(int targetTint, long delay, long duration) {
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ }
+ if (mIconTint == targetTint) {
+ return;
+ }
+ mTintAnimator = ValueAnimator.ofArgb(mIconTint, targetTint);
+ mTintAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setIconTintInternal((Integer) animation.getAnimatedValue());
+ }
+ });
+ mTintAnimator.setDuration(duration);
+ mTintAnimator.setStartDelay(delay);
+ mTintAnimator.setInterpolator(mFastOutSlowIn);
+ mTintAnimator.start();
+ }
+ private void setIconTintInternal(int tint) {
mIconTint = tint;
applyIconTint();
}
+ private void deferIconTintChange(int tint) {
+ if (mTintChangePending && tint == mPendingIconTint) {
+ return;
+ }
+ mTintChangePending = true;
+ mPendingIconTint = tint;
+ }
+
private void applyIconTint() {
for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
@@ -305,4 +371,36 @@
v.setTag(R.id.icon_is_grayscale, grayscale);
return grayscale;
}
+
+ public void appTransitionPending() {
+ mTransitionPending = true;
+ }
+
+ public void appTransitionCancelled() {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingIconTint, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
+ }
+ mTransitionPending = false;
+ }
+
+ public void appTransitionStarting(long startTime, long duration) {
+ if (mTransitionPending && mTintChangePending) {
+ mTintChangePending = false;
+ animateIconTint(mPendingIconTint,
+ Math.max(0, startTime - SystemClock.uptimeMillis()),
+ duration);
+
+ } else if (mTransitionPending) {
+
+ // If we don't have a pending tint change yet, the change might come in the future until
+ // startTime is reached.
+ mTransitionDeferring = true;
+ mTransitionDeferringStartTime = startTime;
+ mTransitionDeferringDuration = duration;
+ mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
+ mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
+ }
+ mTransitionPending = false;
+ }
}
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 19305f3..2f3a159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -257,7 +257,7 @@
}
});
} else {
- mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
+ mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
boolean staying = mPhoneStatusBar.hideKeyguard();
if (!staying) {
mStatusBarWindowManager.setKeyguardFadingAway(true);
@@ -435,4 +435,8 @@
public boolean isInputRestricted() {
return mViewMediatorCallback.isInputRestricted();
}
+
+ public void keyguardGoingAway() {
+ mPhoneStatusBar.keyguardGoingAway();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 0863c86..7ca91a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -22,7 +22,6 @@
boolean isHotspotEnabled();
boolean isHotspotSupported();
void setHotspotEnabled(boolean enabled);
- boolean isProvisioningNeeded();
public interface Callback {
void onHotspotChanged(boolean enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 5eff5a6..4bfd528 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,45 +16,38 @@
package com.android.systemui.statusbar.policy;
-import android.app.ActivityManager;
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.net.ConnectivityManager;
import android.net.wifi.WifiManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
+import com.android.settingslib.TetherUtil;
+
import java.util.ArrayList;
public class HotspotControllerImpl implements HotspotController {
private static final String TAG = "HotspotController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- // Keep these in sync with Settings TetherService.java
- public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
- public static final String EXTRA_SET_ALARM = "extraSetAlarm";
- public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
- public static final String EXTRA_ENABLE_WIFI_TETHER = "extraEnableWifiTether";
- // Keep this in sync with Settings TetherSettings.java
- public static final int WIFI_TETHERING = 0;
+ private static final Intent TETHER_SERVICE_INTENT = new Intent()
+ .putExtra(TetherUtil.EXTRA_ADD_TETHER_TYPE, TetherUtil.TETHERING_WIFI)
+ .putExtra(TetherUtil.EXTRA_SET_ALARM, true)
+ .putExtra(TetherUtil.EXTRA_RUN_PROVISION, true)
+ .putExtra(TetherUtil.EXTRA_ENABLE_WIFI_TETHER, true)
+ .setComponent(TetherUtil.TETHER_SERVICE);
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final Receiver mReceiver = new Receiver();
private final Context mContext;
private final WifiManager mWifiManager;
- private final ConnectivityManager mConnectivityManager;
public HotspotControllerImpl(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
- mConnectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
}
public void addCallback(Callback callback) {
@@ -78,54 +71,17 @@
@Override
public boolean isHotspotSupported() {
- final boolean isSecondaryUser = ActivityManager.getCurrentUser() != UserHandle.USER_OWNER;
- return !isSecondaryUser && mConnectivityManager.isTetheringSupported();
- }
-
- @Override
- public boolean isProvisioningNeeded() {
- // Keep in sync with other usage of config_mobile_hotspot_provision_app.
- // TetherSettings#isProvisioningNeeded and
- // ConnectivityManager#enforceTetherChangePermission
- String[] provisionApp = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_mobile_hotspot_provision_app);
- if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
- || provisionApp == null) {
- return false;
- }
- return (provisionApp.length == 2);
+ return TetherUtil.isTetheringSupported(mContext);
}
@Override
public void setHotspotEnabled(boolean enabled) {
final ContentResolver cr = mContext.getContentResolver();
// Call provisioning app which is called when enabling Tethering from Settings
- if (enabled) {
- if (isProvisioningNeeded()) {
- String tetherEnable = mContext.getResources().getString(
- com.android.internal.R.string.config_wifi_tether_enable);
- Intent intent = new Intent();
- intent.putExtra(EXTRA_ADD_TETHER_TYPE, WIFI_TETHERING);
- intent.putExtra(EXTRA_SET_ALARM, true);
- intent.putExtra(EXTRA_RUN_PROVISION, true);
- intent.putExtra(EXTRA_ENABLE_WIFI_TETHER, true);
- intent.setComponent(ComponentName.unflattenFromString(tetherEnable));
- mContext.startServiceAsUser(intent, UserHandle.CURRENT);
- } else {
- int wifiState = mWifiManager.getWifiState();
- if ((wifiState == WifiManager.WIFI_STATE_ENABLING) ||
- (wifiState == WifiManager.WIFI_STATE_ENABLED)) {
- mWifiManager.setWifiEnabled(false);
- Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1);
- }
- mWifiManager.setWifiApEnabled(null, true);
- }
+ if (enabled && TetherUtil.isProvisioningNeeded(mContext)) {
+ mContext.startServiceAsUser(TETHER_SERVICE_INTENT, UserHandle.CURRENT);
} else {
- mWifiManager.setWifiApEnabled(null, false);
- if (Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0) == 1) {
- mWifiManager.setWifiEnabled(true);
- Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0);
- }
+ TetherUtil.setWifiTethering(enabled, mContext);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 8379b93..1d96c6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -36,7 +36,7 @@
// Save the previous SignalController.States of all SignalControllers for dumps.
static final boolean RECORD_HISTORY = true;
// If RECORD_HISTORY how many to save, must be a power of 2.
- static final int HISTORY_SIZE = 16;
+ static final int HISTORY_SIZE = 64;
protected static final boolean DEBUG = NetworkControllerImpl.DEBUG;
protected static final boolean CHATTY = NetworkControllerImpl.CHATTY;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index dbdb578..bea0c86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.policy;
import android.app.AlarmManager;
-import android.app.INotificationManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -28,8 +27,6 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
@@ -53,7 +50,7 @@
private final Context mContext;
private final GlobalSetting mModeSetting;
private final GlobalSetting mConfigSetting;
- private final INotificationManager mNoMan;
+ private final NotificationManager mNoMan;
private final LinkedHashMap<Uri, Condition> mConditions = new LinkedHashMap<Uri, Condition>();
private final AlarmManager mAlarmManager;
private final SetupObserver mSetupObserver;
@@ -78,8 +75,7 @@
};
mModeSetting.setListening(true);
mConfigSetting.setListening(true);
- mNoMan = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mSetupObserver = new SetupObserver(handler);
mSetupObserver.register();
@@ -113,11 +109,7 @@
@Override
public void requestConditions(boolean request) {
mRequesting = request;
- try {
- mNoMan.requestZenModeConditions(mListener, request ? Condition.FLAG_RELEVANT_NOW : 0);
- } catch (RemoteException e) {
- // noop
- }
+ mNoMan.requestZenModeConditions(mListener, request ? Condition.FLAG_RELEVANT_NOW : 0);
if (!mRequesting) {
mConditions.clear();
}
@@ -125,24 +117,12 @@
@Override
public void setExitCondition(Condition exitCondition) {
- try {
- mNoMan.setZenModeCondition(exitCondition);
- } catch (RemoteException e) {
- // noop
- }
+ mNoMan.setZenModeCondition(exitCondition);
}
@Override
public Condition getExitCondition() {
- try {
- final ZenModeConfig config = mNoMan.getZenModeConfig();
- if (config != null) {
- return config.exitCondition;
- }
- } catch (RemoteException e) {
- // noop
- }
- return null;
+ return mNoMan.getZenModeCondition();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 6f2a392..413c891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -170,4 +170,16 @@
@Override
public void showScreenPinningRequest() {
}
+
+ @Override
+ public void appTransitionPending() {
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ }
+
+ @Override
+ public void appTransitionStarting(long startTime, long duration) {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 7102c2a..5e3ec3f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -1,31 +1,3 @@
-package com.android.systemui.volume;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.media.AudioManager;
-import android.media.IRemoteVolumeController;
-import android.media.IVolumeController;
-import android.media.session.ISessionController;
-import android.media.session.MediaController;
-import android.media.session.MediaSessionManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Log;
-
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
/*
* Copyright (C) 2014 The Android Open Source Project
*
@@ -42,19 +14,61 @@
* limitations under the License.
*/
+package com.android.systemui.volume;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.media.IRemoteVolumeController;
+import android.media.IVolumeController;
+import android.media.session.ISessionController;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.statusbar.ServiceMonitor;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
public class VolumeUI extends SystemUI {
private static final String TAG = "VolumeUI";
- private static final String SETTING = "systemui_volume_controller"; // for testing
- private static final Uri SETTING_URI = Settings.Global.getUriFor(SETTING);
- private static final int DEFAULT = 1; // enabled by default
+ private static boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
private final Handler mHandler = new Handler();
+ private final Receiver mReceiver = new Receiver();
+ private final RestorationNotification mRestorationNotification = new RestorationNotification();
private boolean mEnabled;
private AudioManager mAudioManager;
+ private NotificationManager mNotificationManager;
private MediaSessionManager mMediaSessionManager;
private VolumeController mVolumeController;
private RemoteVolumeController mRemoteVolumeController;
+ private ServiceMonitor mVolumeControllerService;
private VolumePanel mPanel;
private int mDismissDelay;
@@ -64,14 +78,19 @@
mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
if (!mEnabled) return;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mNotificationManager =
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mMediaSessionManager = (MediaSessionManager) mContext
.getSystemService(Context.MEDIA_SESSION_SERVICE);
initPanel();
mVolumeController = new VolumeController();
mRemoteVolumeController = new RemoteVolumeController();
putComponent(VolumeComponent.class, mVolumeController);
- updateController();
- mContext.getContentResolver().registerContentObserver(SETTING_URI, false, mObserver);
+ mReceiver.start();
+ mVolumeControllerService = new ServiceMonitor(TAG, LOGD,
+ mContext, Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT,
+ new ServiceMonitorCallbacks());
+ mVolumeControllerService.start();
}
@Override
@@ -85,18 +104,20 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print("mEnabled="); pw.println(mEnabled);
+ pw.print("mVolumeControllerService="); pw.println(mVolumeControllerService.getComponent());
if (mPanel != null) {
mPanel.dump(fd, pw, args);
}
}
- private void updateController() {
- if (Settings.Global.getInt(mContext.getContentResolver(), SETTING, DEFAULT) != 0) {
- Log.d(TAG, "Registering volume controller");
+ private void setVolumeController(boolean register) {
+ if (register) {
+ if (LOGD) Log.d(TAG, "Registering volume controller");
mAudioManager.setVolumeController(mVolumeController);
mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
+ DndTile.setVisible(mContext, false);
} else {
- Log.d(TAG, "Unregistering volume controller");
+ if (LOGD) Log.d(TAG, "Unregistering volume controller");
mAudioManager.setVolumeController(null);
mMediaSessionManager.setRemoteVolumeController(null);
}
@@ -129,13 +150,32 @@
});
}
- private final ContentObserver mObserver = new ContentObserver(mHandler) {
- public void onChange(boolean selfChange, Uri uri) {
- if (SETTING_URI.equals(uri)) {
- updateController();
+ private String getAppLabel(ComponentName component) {
+ final String pkg = component.getPackageName();
+ try {
+ final ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(pkg, 0);
+ final String rt = mContext.getPackageManager().getApplicationLabel(ai).toString();
+ if (!TextUtils.isEmpty(rt)) {
+ return rt;
}
+ } catch (Exception e) {
+ Log.w(TAG, "Error loading app label", e);
}
- };
+ return pkg;
+ }
+
+ private void showServiceActivationDialog(final ComponentName component) {
+ final SystemUIDialog d = new SystemUIDialog(mContext);
+ d.setMessage(mContext.getString(R.string.volumeui_prompt_message, getAppLabel(component)));
+ d.setPositiveButton(R.string.volumeui_prompt_allow, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mVolumeControllerService.setComponent(component);
+ }
+ });
+ d.setNegativeButton(R.string.volumeui_prompt_deny, null);
+ d.show();
+ }
private final Runnable mStartZenSettings = new Runnable() {
@Override
@@ -213,4 +253,83 @@
// than by remoteVolumeChanged.
}
}
+
+ private final class ServiceMonitorCallbacks implements ServiceMonitor.Callbacks {
+ @Override
+ public void onNoService() {
+ if (LOGD) Log.d(TAG, "onNoService");
+ setVolumeController(true);
+ mRestorationNotification.hide();
+ }
+
+ @Override
+ public long onServiceStartAttempt() {
+ if (LOGD) Log.d(TAG, "onServiceStartAttempt");
+ setVolumeController(false);
+ mVolumeController.dismissNow();
+ mRestorationNotification.show();
+ return 0;
+ }
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ private static final String ENABLE = "com.android.systemui.vui.ENABLE";
+ private static final String DISABLE = "com.android.systemui.vui.DISABLE";
+ private static final String EXTRA_COMPONENT = "component";
+
+ public void start() {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(ENABLE);
+ filter.addAction(DISABLE);
+ mContext.registerReceiver(this, filter, null, mHandler);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
+ final boolean current = component.equals(mVolumeControllerService.getComponent());
+ if (ENABLE.equals(action) && component != null) {
+ if (!current) {
+ showServiceActivationDialog(component);
+ }
+ }
+ if (DISABLE.equals(action) && component != null) {
+ if (current) {
+ mVolumeControllerService.setComponent(null);
+ }
+ }
+ }
+ }
+
+ private final class RestorationNotification {
+ public void hide() {
+ mNotificationManager.cancel(R.id.notification_volumeui);
+ }
+
+ public void show() {
+ final ComponentName component = mVolumeControllerService.getComponent();
+ if (component == null) {
+ Log.w(TAG, "Not showing restoration notification, component not active");
+ return;
+ }
+ final Intent intent = new Intent(Receiver.DISABLE)
+ .putExtra(Receiver.EXTRA_COMPONENT, component);
+ mNotificationManager.notify(R.id.notification_volumeui,
+ new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_ringer_audible)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setOngoing(true)
+ .setContentTitle(mContext.getString(
+ R.string.volumeui_notification_title, getAppLabel(component)))
+ .setContentText(mContext.getString(R.string.volumeui_notification_text))
+ .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent, 0))
+ .setPriority(Notification.PRIORITY_MIN)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getResources().getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .build());
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 5726fa7..6cecc8f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -90,9 +90,11 @@
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
private SegmentedButtons mZenButtons;
+ private ViewGroup mZenButtonsContainer;
private View mZenSubhead;
private TextView mZenSubheadCollapsed;
private TextView mZenSubheadExpanded;
+ private View mZenEmbeddedDivider;
private View mMoreSettings;
private LinearLayout mZenConditions;
@@ -114,6 +116,7 @@
private Condition mSessionExitCondition;
private Condition[] mConditions;
private Condition mTimeCondition;
+ private boolean mEmbedded;
public ZenModePanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -140,9 +143,25 @@
pw.print(" mExpanded="); pw.println(mExpanded);
pw.print(" mSessionZen="); pw.println(mSessionZen);
pw.print(" mAttachedZen="); pw.println(mAttachedZen);
+ pw.print(" mEmbedded="); pw.println(mEmbedded);
mTransitionHelper.dump(fd, pw, args);
}
+ public void setEmbedded(boolean embedded) {
+ if (mEmbedded == embedded) return;
+ mEmbedded = embedded;
+ mZenButtonsContainer.setLayoutTransition(mEmbedded ? null : newLayoutTransition(null));
+ if (mEmbedded) {
+ mZenButtonsContainer.setBackground(null);
+ } else {
+ mZenButtonsContainer.setBackgroundResource(R.drawable.qs_background_secondary);
+ }
+ mZenButtons.getChildAt(2).setVisibility(mEmbedded ? GONE : VISIBLE);
+ mZenEmbeddedDivider.setVisibility(mEmbedded ? VISIBLE : GONE);
+ setExpanded(mEmbedded);
+ updateWidgets();
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -156,10 +175,11 @@
Global.ZEN_MODE_OFF);
mZenButtons.setCallback(mZenButtonsCallback);
- final ViewGroup zenButtonsContainer = (ViewGroup) findViewById(R.id.zen_buttons_container);
- zenButtonsContainer.setLayoutTransition(newLayoutTransition(null));
+ mZenButtonsContainer = (ViewGroup) findViewById(R.id.zen_buttons_container);
+ mZenButtonsContainer.setLayoutTransition(newLayoutTransition(null));
mZenSubhead = findViewById(R.id.zen_subhead);
+ mZenEmbeddedDivider = findViewById(R.id.zen_embedded_divider);
mZenSubheadCollapsed = (TextView) findViewById(R.id.zen_subhead_collapsed);
mZenSubheadCollapsed.setOnClickListener(new View.OnClickListener() {
@@ -222,7 +242,9 @@
mAttachedZen = -1;
mSessionZen = -1;
setSessionExitCondition(null);
- setExpanded(false);
+ if (!mEmbedded) {
+ setExpanded(false);
+ }
setRequestingConditions(false);
mTransitionHelper.clear();
}
@@ -361,7 +383,7 @@
private void handleUpdateZen(int zen) {
if (mSessionZen != -1 && mSessionZen != zen) {
- setExpanded(zen != Global.ZEN_MODE_OFF);
+ setExpanded(mEmbedded || zen != Global.ZEN_MODE_OFF);
mSessionZen = zen;
}
mZenButtons.setSelectedValue(zen);
@@ -403,7 +425,7 @@
final boolean expanded = !mHidden && mExpanded;
mZenButtons.setVisibility(mHidden ? GONE : VISIBLE);
- mZenSubhead.setVisibility(!mHidden && !zenOff ? VISIBLE : GONE);
+ mZenSubhead.setVisibility(!mHidden && !zenOff && !mEmbedded ? VISIBLE : GONE);
mZenSubheadExpanded.setVisibility(expanded ? VISIBLE : GONE);
mZenSubheadCollapsed.setVisibility(!expanded ? VISIBLE : GONE);
mMoreSettings.setVisibility(zenImportant && expanded ? VISIBLE : GONE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 7fa3f68..aefb1bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -248,6 +248,11 @@
}
}
+ public void testHistorySize() {
+ // Verify valid history size, otherwise it gits printed out the wrong order and whatnot.
+ assertEquals(0, SignalController.HISTORY_SIZE & (SignalController.HISTORY_SIZE - 1));
+ }
+
private void setCdma() {
setIsGsm(false);
updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 5e150e9..417bfe2 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -887,8 +887,59 @@
return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
}
+ native void rsnScriptIntrinsicBLAS_Single(long con, long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ float alpha, long A, long B, float beta, long C, int incX, int incY,
+ int KL, int KU);
+ synchronized void nScriptIntrinsicBLAS_Single(long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ float alpha, long A, long B, float beta, long C, int incX, int incY,
+ int KL, int KU) {
+ validate();
+ rsnScriptIntrinsicBLAS_Single(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU);
+ }
+
+ native void rsnScriptIntrinsicBLAS_Double(long con, long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ double alpha, long A, long B, double beta, long C, int incX, int incY,
+ int KL, int KU);
+ synchronized void nScriptIntrinsicBLAS_Double(long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ double alpha, long A, long B, double beta, long C, int incX, int incY,
+ int KL, int KU) {
+ validate();
+ rsnScriptIntrinsicBLAS_Double(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alpha, A, B, beta, C, incX, incY, KL, KU);
+ }
+
+ native void rsnScriptIntrinsicBLAS_Complex(long con, long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
+ int KL, int KU);
+ synchronized void nScriptIntrinsicBLAS_Complex(long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ float alphaX, float alphaY, long A, long B, float betaX, float betaY, long C, int incX, int incY,
+ int KL, int KU) {
+ validate();
+ rsnScriptIntrinsicBLAS_Complex(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU);
+ }
+
+ native void rsnScriptIntrinsicBLAS_Z(long con, long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
+ int KL, int KU);
+ synchronized void nScriptIntrinsicBLAS_Z(long id, int func, int TransA,
+ int TransB, int Side, int Uplo, int Diag, int M, int N, int K,
+ double alphaX, double alphaY, long A, long B, double betaX, double betaY, long C, int incX, int incY,
+ int KL, int KU) {
+ validate();
+ rsnScriptIntrinsicBLAS_Z(mContext, id, func, TransA, TransB, Side, Uplo, Diag, M, N, K, alphaX, alphaY, A, B, betaX, betaY, C, incX, incY, KL, KU);
+ }
+
+
long mDev;
long mContext;
+ private boolean mDestroyed = false;
+
@SuppressWarnings({"FieldCanBeLocal"})
MessageThread mMessageThread;
@@ -1333,6 +1384,38 @@
nContextFinish();
}
+ private void helpDestroy() {
+ boolean shouldDestroy = false;
+ synchronized(this) {
+ if (!mDestroyed) {
+ shouldDestroy = true;
+ mDestroyed = true;
+ }
+ }
+
+ if (shouldDestroy) {
+ nContextFinish();
+
+ nContextDeinitToClient(mContext);
+ mMessageThread.mRun = false;
+ try {
+ mMessageThread.join();
+ } catch(InterruptedException e) {
+ }
+
+ nContextDestroy();
+
+ nDeviceDestroy(mDev);
+ mDev = 0;
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ helpDestroy();
+ super.finalize();
+ }
+
+
/**
* Destroys this RenderScript context. Once this function is called,
* using this context or any objects belonging to this context is
@@ -1341,19 +1424,7 @@
*/
public void destroy() {
validate();
- nContextFinish();
-
- nContextDeinitToClient(mContext);
- mMessageThread.mRun = false;
- try {
- mMessageThread.join();
- } catch(InterruptedException e) {
- }
-
- nContextDestroy();
-
- nDeviceDestroy(mDev);
- mDev = 0;
+ helpDestroy();
}
boolean isAlive() {
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
new file mode 100644
index 0000000..90d2300
--- /dev/null
+++ b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
@@ -0,0 +1,1489 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.annotation.IntDef;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ *
+ * BLAS
+ *
+ * @hide
+ **/
+public final class ScriptIntrinsicBLAS extends ScriptIntrinsic {
+ private Allocation mLUT;
+
+ private ScriptIntrinsicBLAS(long id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ private static final int RsBlas_sdsdot = 1;
+ private static final int RsBlas_dsdot = 2;
+ private static final int RsBlas_sdot = 3;
+ private static final int RsBlas_ddot = 4;
+ private static final int RsBlas_cdotu_sub = 5;
+ private static final int RsBlas_cdotc_sub = 6;
+ private static final int RsBlas_zdotu_sub = 7;
+ private static final int RsBlas_zdotc_sub = 8;
+ private static final int RsBlas_snrm2 = 9;
+ private static final int RsBlas_sasum = 10;
+ private static final int RsBlas_dnrm2 = 11;
+ private static final int RsBlas_dasum = 12;
+ private static final int RsBlas_scnrm2 = 13;
+ private static final int RsBlas_scasum = 14;
+ private static final int RsBlas_dznrm2 = 15;
+ private static final int RsBlas_dzasum = 16;
+ private static final int RsBlas_isamax = 17;
+ private static final int RsBlas_idamax = 18;
+ private static final int RsBlas_icamax = 19;
+ private static final int RsBlas_izamax = 20;
+ private static final int RsBlas_sswap = 21;
+ private static final int RsBlas_scopy = 22;
+ private static final int RsBlas_saxpy = 23;
+ private static final int RsBlas_dswap = 24;
+ private static final int RsBlas_dcopy = 25;
+ private static final int RsBlas_daxpy = 26;
+ private static final int RsBlas_cswap = 27;
+ private static final int RsBlas_ccopy = 28;
+ private static final int RsBlas_caxpy = 29;
+ private static final int RsBlas_zswap = 30;
+ private static final int RsBlas_zcopy = 31;
+ private static final int RsBlas_zaxpy = 32;
+ private static final int RsBlas_srotg = 33;
+ private static final int RsBlas_srotmg = 34;
+ private static final int RsBlas_srot = 35;
+ private static final int RsBlas_srotm = 36;
+ private static final int RsBlas_drotg = 37;
+ private static final int RsBlas_drotmg = 38;
+ private static final int RsBlas_drot = 39;
+ private static final int RsBlas_drotm = 40;
+ private static final int RsBlas_sscal = 41;
+ private static final int RsBlas_dscal = 42;
+ private static final int RsBlas_cscal = 43;
+ private static final int RsBlas_zscal = 44;
+ private static final int RsBlas_csscal = 45;
+ private static final int RsBlas_zdscal = 46;
+ private static final int RsBlas_sgemv = 47;
+ private static final int RsBlas_sgbmv = 48;
+ private static final int RsBlas_strmv = 49;
+ private static final int RsBlas_stbmv = 50;
+ private static final int RsBlas_stpmv = 51;
+ private static final int RsBlas_strsv = 52;
+ private static final int RsBlas_stbsv = 53;
+ private static final int RsBlas_stpsv = 54;
+ private static final int RsBlas_dgemv = 55;
+ private static final int RsBlas_dgbmv = 56;
+ private static final int RsBlas_dtrmv = 57;
+ private static final int RsBlas_dtbmv = 58;
+ private static final int RsBlas_dtpmv = 59;
+ private static final int RsBlas_dtrsv = 60;
+ private static final int RsBlas_dtbsv = 61;
+ private static final int RsBlas_dtpsv = 62;
+ private static final int RsBlas_cgemv = 63;
+ private static final int RsBlas_cgbmv = 64;
+ private static final int RsBlas_ctrmv = 65;
+ private static final int RsBlas_ctbmv = 66;
+ private static final int RsBlas_ctpmv = 67;
+ private static final int RsBlas_ctrsv = 68;
+ private static final int RsBlas_ctbsv = 69;
+ private static final int RsBlas_ctpsv = 70;
+ private static final int RsBlas_zgemv = 71;
+ private static final int RsBlas_zgbmv = 72;
+ private static final int RsBlas_ztrmv = 73;
+ private static final int RsBlas_ztbmv = 74;
+ private static final int RsBlas_ztpmv = 75;
+ private static final int RsBlas_ztrsv = 76;
+ private static final int RsBlas_ztbsv = 77;
+ private static final int RsBlas_ztpsv = 78;
+ private static final int RsBlas_ssymv = 79;
+ private static final int RsBlas_ssbmv = 80;
+ private static final int RsBlas_sspmv = 81;
+ private static final int RsBlas_sger = 82;
+ private static final int RsBlas_ssyr = 83;
+ private static final int RsBlas_sspr = 84;
+ private static final int RsBlas_ssyr2 = 85;
+ private static final int RsBlas_sspr2 = 86;
+ private static final int RsBlas_dsymv = 87;
+ private static final int RsBlas_dsbmv = 88;
+ private static final int RsBlas_dspmv = 89;
+ private static final int RsBlas_dger = 90;
+ private static final int RsBlas_dsyr = 91;
+ private static final int RsBlas_dspr = 92;
+ private static final int RsBlas_dsyr2 = 93;
+ private static final int RsBlas_dspr2 = 94;
+ private static final int RsBlas_chemv = 95;
+ private static final int RsBlas_chbmv = 96;
+ private static final int RsBlas_chpmv = 97;
+ private static final int RsBlas_cgeru = 98;
+ private static final int RsBlas_cgerc = 99;
+ private static final int RsBlas_cher = 100;
+ private static final int RsBlas_chpr = 101;
+ private static final int RsBlas_cher2 = 102;
+ private static final int RsBlas_chpr2 = 103;
+ private static final int RsBlas_zhemv = 104;
+ private static final int RsBlas_zhbmv = 105;
+ private static final int RsBlas_zhpmv = 106;
+ private static final int RsBlas_zgeru = 107;
+ private static final int RsBlas_zgerc = 108;
+ private static final int RsBlas_zher = 109;
+ private static final int RsBlas_zhpr = 110;
+ private static final int RsBlas_zher2 = 111;
+ private static final int RsBlas_zhpr2 = 112;
+ private static final int RsBlas_sgemm = 113;
+ private static final int RsBlas_ssymm = 114;
+ private static final int RsBlas_ssyrk = 115;
+ private static final int RsBlas_ssyr2k = 116;
+ private static final int RsBlas_strmm = 117;
+ private static final int RsBlas_strsm = 118;
+ private static final int RsBlas_dgemm = 119;
+ private static final int RsBlas_dsymm = 120;
+ private static final int RsBlas_dsyrk = 121;
+ private static final int RsBlas_dsyr2k = 122;
+ private static final int RsBlas_dtrmm = 123;
+ private static final int RsBlas_dtrsm = 124;
+ private static final int RsBlas_cgemm = 125;
+ private static final int RsBlas_csymm = 126;
+ private static final int RsBlas_csyrk = 127;
+ private static final int RsBlas_csyr2k = 128;
+ private static final int RsBlas_ctrmm = 129;
+ private static final int RsBlas_ctrsm = 130;
+ private static final int RsBlas_zgemm = 131;
+ private static final int RsBlas_zsymm = 132;
+ private static final int RsBlas_zsyrk = 133;
+ private static final int RsBlas_zsyr2k = 134;
+ private static final int RsBlas_ztrmm = 135;
+ private static final int RsBlas_ztrsm = 136;
+ private static final int RsBlas_chemm = 137;
+ private static final int RsBlas_cherk = 138;
+ private static final int RsBlas_cher2k = 139;
+ private static final int RsBlas_zhemm = 140;
+ private static final int RsBlas_zherk = 141;
+ private static final int RsBlas_zher2k = 142;
+
+ /**
+ */
+ public static ScriptIntrinsicBLAS create(RenderScript rs) {
+ long id = rs.nScriptIntrinsicCreate(13, Element.U32(rs).getID(rs));
+ return new ScriptIntrinsicBLAS(id, rs);
+ }
+
+ @IntDef({NO_TRANSPOSE, TRANSPOSE, CONJ_TRANSPOSE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Transpose {}
+
+ @IntDef({UPPER, LOWER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Uplo {}
+
+ @IntDef({NON_UNIT, UNIT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Diag {}
+
+ @IntDef({LEFT, RIGHT})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Side {}
+
+ public static final int NO_TRANSPOSE = 111;
+ public static final int TRANSPOSE = 112;
+ public static final int CONJ_TRANSPOSE = 113;
+
+ public static final int UPPER = 121;
+ public static final int LOWER = 122;
+
+ public static final int NON_UNIT = 131;
+ public static final int UNIT = 132;
+
+ public static final int LEFT = 141;
+ public static final int RIGHT = 142;
+
+ static void validateSide(@Side int Side) {
+ if (Side != LEFT && Side != RIGHT) {
+ throw new RSRuntimeException("Invalid side passed to BLAS");
+ }
+ }
+
+ static void validateTranspose(@Transpose int Trans) {
+ if (Trans != NO_TRANSPOSE && Trans != TRANSPOSE &&
+ Trans != CONJ_TRANSPOSE) {
+ throw new RSRuntimeException("Invalid transpose passed to BLAS");
+ }
+ }
+
+ static void validateConjTranspose(@Transpose int Trans) {
+ if (Trans != NO_TRANSPOSE &&
+ Trans != CONJ_TRANSPOSE) {
+ throw new RSRuntimeException("Invalid transpose passed to BLAS");
+ }
+ }
+
+ static void validateDiag(@Diag int Diag) {
+ if (Diag != NON_UNIT && Diag != UNIT) {
+ throw new RSRuntimeException("Invalid diag passed to BLAS");
+ }
+ }
+
+ static void validateUplo(@Uplo int Uplo) {
+ if (Uplo != LEFT && Uplo != RIGHT) {
+ throw new RSRuntimeException("Invalid uplo passed to BLAS");
+ }
+ }
+
+
+ /**
+ * Level 2 BLAS
+ */
+
+ static void validateGEMV(Element e, int TransA, Allocation A, Allocation X, int incX, Allocation Y, int incY) {
+ validateTranspose(TransA);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (incX <= 0 || incY <= 0) {
+ throw new RSRuntimeException("Vector increments must be greater than 0");
+ }
+ int expectedXDim = -1, expectedYDim = -1;
+ if (TransA == NO_TRANSPOSE) {
+ expectedXDim = 1 + (N - 1) * incX;
+ expectedYDim = 1 + (M - 1) * incY;
+ } else {
+ expectedXDim = 1 + (M - 1) * incX;
+ expectedYDim = 1 + (N - 1) * incY;
+ }
+ if (X.getType().getX() != expectedXDim ||
+ Y.getType().getY() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for GEMV");
+ }
+ }
+ void SGEMV(@Transpose int TransA, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+ validateGEMV(Element.F32(mRS), TransA, A, X, incX, Y, incY);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void DGEMV(@Transpose int TransA, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+ validateGEMV(Element.F64(mRS), TransA, A, X, incX, Y, incY);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void CGEMV(@Transpose int TransA, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+ validateGEMV(Element.F32_2(mRS), TransA, A, X, incX, Y, incY);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZGEMV(@Transpose int TransA, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+ validateGEMV(Element.F64_2(mRS), TransA, A, X, incX, Y, incY);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgemv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+
+ void SGBMV(@Transpose int TransA, int KL, int KU, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+ // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+ validateGEMV(Element.F32(mRS), TransA, A, X, incX, Y, incY);
+ if (KL < 0 || KU < 0) {
+ throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+ }
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, KL, KU);
+ }
+ void DGBMV(@Transpose int TransA, int KL, int KU, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+ // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+ validateGEMV(Element.F64(mRS), TransA, A, X, incX, Y, incY);
+ if (KL < 0 || KU < 0) {
+ throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+ }
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, KL, KU);
+ }
+ void CGBMV(@Transpose int TransA, int KL, int KU, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+ // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+ validateGEMV(Element.F32_2(mRS), TransA, A, X, incX, Y, incY);
+ if (KL < 0 || KU < 0) {
+ throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+ }
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, KL, KU);
+ }
+ void ZGBMV(@Transpose int TransA, int KL, int KU, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+ // GBMV has the same validation requirements as GEMV + KL and KU >= 0
+ validateGEMV(Element.F64_2(mRS), TransA, A, X, incX, Y, incY);
+ if (KL < 0 || KU < 0) {
+ throw new RSRuntimeException("KL and KU must be greater than or equal to 0");
+ }
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgbmv, TransA, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, KL, KU);
+ }
+
+ static void validateTRMV(Element e, @Transpose int TransA, Allocation A, Allocation X, int incX) {
+ validateTranspose(TransA);
+ int N = A.getType().getY();
+ if (A.getType().getX() != N) {
+ throw new RSRuntimeException("A must be a square matrix for TRMV");
+ }
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (incX <= 0) {
+ throw new RSRuntimeException("Vector increments must be greater than 0");
+ }
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for TRMV");
+ }
+ }
+
+ static int validateTPMV(Element e, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ validateTranspose(TransA);
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ if (!Ap.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (Ap.getType().getY() > 1) {
+ throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+ }
+
+ int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+ if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+ throw new RSRuntimeException("Invalid dimension for Ap");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SYMV");
+ }
+
+ return N;
+ }
+
+ void STRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ validateTRMV(Element.F32(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void DTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ validateTRMV(Element.F64(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void CTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ validateTRMV(Element.F32_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void ZTRMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ validateTRMV(Element.F64_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void STBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBMV has the same requirements as TRMV
+ validateTRMV(Element.F32(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void DTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBMV has the same requirements as TRMV
+ validateTRMV(Element.F64(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void CTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBMV has the same requirements as TRMV
+ validateTRMV(Element.F32_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void ZTBMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBMV has the same requirements as TRMV
+ validateTRMV(Element.F64_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztbmv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void STPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ int N = validateTPMV(Element.F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void DTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ int N = validateTPMV(Element.F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void CTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ int N = validateTPMV(Element.F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void ZTPMV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ int N = validateTPMV(Element.F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztpmv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void STRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ // TRSV is the same as TRMV
+ validateTRMV(Element.F32(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+
+ }
+ void DTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ // TRSV is the same as TRMV
+ validateTRMV(Element.F64(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+
+ }
+ void CTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ // TRSV is the same as TRMV
+ validateTRMV(Element.F32_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+
+ }
+ void ZTRSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation A, Allocation X, int incX) {
+ // TRSV is the same as TRMV
+ validateTRMV(Element.F64_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztrsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+
+ }
+ void STBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBSV is the same as TRMV
+ validateTRMV(Element.F32(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ if (K < 0) {
+ throw new RSRuntimeException("Number of diagonals must be positive");
+ }
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void DTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBSV is the same as TRMV
+ validateTRMV(Element.F64(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ if (K < 0) {
+ throw new RSRuntimeException("Number of diagonals must be positive");
+ }
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, A.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void CTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBSV is the same as TRMV
+ validateTRMV(Element.F32_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ if (K < 0) {
+ throw new RSRuntimeException("Number of diagonals must be positive");
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void ZTBSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, int K, Allocation A, Allocation X, int incX) {
+ // TBSV is the same as TRMV
+ validateTRMV(Element.F64_2(mRS), TransA, A, X, incX);
+ int N = A.getType().getY();
+ if (K < 0) {
+ throw new RSRuntimeException("Number of diagonals must be positive");
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztbsv, TransA, 0, 0, Uplo, Diag, 0, N, K, 0, 0, A.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void STPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ // TPSV is same as TPMV
+ int N = validateTPMV(Element.F32(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_stpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void DTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ // TPSV is same as TPMV
+ int N = validateTPMV(Element.F64(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dtpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, incX, 0, 0, 0);
+ }
+ void CTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ // TPSV is same as TPMV
+ int N = validateTPMV(Element.F32_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ctpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+ void ZTPSV(@Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Allocation Ap, Allocation X, int incX) {
+ // TPSV is same as TPMV
+ int N = validateTPMV(Element.F64_2(mRS), Uplo, TransA, Diag, Ap, X, incX);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ztpsv, TransA, 0, 0, Uplo, Diag, 0, N, 0, 0, 0, Ap.getID(mRS), X.getID(mRS), 0, 0, 0, incX, 0, 0, 0);
+ }
+
+ /**
+ * Level 2, S and D only
+ */
+ static int validateSYMV(Element e, @Uplo int Uplo, Allocation A, Allocation X, Allocation Y, int incX, int incY) {
+ validateUplo(Uplo);
+ int N = A.getType().getY();
+ if (A.getType().getX() != N) {
+ throw new RSRuntimeException("A must be a square matrix for SYMV");
+ }
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e) ) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (incX <= 0 || incY <= 0) {
+ throw new RSRuntimeException("Vector increments must be greater than 0");
+ }
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SYMV");
+ }
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SYMV");
+ }
+ return N;
+ }
+ static int validateSPMV(Element e, @Uplo int Uplo, Allocation Ap, Allocation X, int incX, Allocation Y, int incY) {
+ validateUplo(Uplo);
+ if (!Ap.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (Ap.getType().getY() > 1) {
+ throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+ }
+
+ int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+ if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+ throw new RSRuntimeException("Invalid dimension for Ap");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+ }
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+ }
+
+ return N;
+ }
+ static void validateGER(Element e, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e) ) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+
+ if (N < 1 || M < 1) {
+ throw new RSRuntimeException("M and N must be 1 or greater for GER");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for GER");
+ }
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for GER");
+ }
+
+
+ }
+ static int validateSYR(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation A) {
+ validateUplo(Uplo);
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+
+ int N = A.getType().getX();
+
+ if (X.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+ if (N != A.getType().getY()) {
+ throw new RSRuntimeException("A must be a symmetric matrix");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SYR");
+ }
+ return N;
+ }
+ static int validateSPR(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Ap) {
+ validateUplo(Uplo);
+ if (!Ap.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (Ap.getType().getY() > 1) {
+ throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+ }
+
+ int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+ if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+ throw new RSRuntimeException("Invalid dimension for Ap");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+ }
+
+ return N;
+ }
+
+ static int validateSYR2(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ validateUplo(Uplo);
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ int N = A.getType().getX();
+
+ if (N != A.getType().getY()) {
+ throw new RSRuntimeException("A must be a symmetric matrix");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (X.getType().getX() != expectedXDim || Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SYR");
+ }
+ return N;
+
+ }
+ static int validateSPR2(Element e, @Uplo int Uplo, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+ validateUplo(Uplo);
+ if (!Ap.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ if (Ap.getType().getY() > 1) {
+ throw new RSRuntimeException("Ap must have a Y dimension of 0 or 1");
+ }
+
+ int N = (int)Math.sqrt((double)Ap.getType().getX() * 2);
+ if (Ap.getType().getX() != ((N * (N+1)) / 2)) {
+ throw new RSRuntimeException("Invalid dimension for Ap");
+ }
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (X.getType().getX() != expectedXDim || Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for SPMV");
+ }
+
+ return N;
+ }
+
+ void SSYMV(@Uplo int Uplo, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+ int N = validateSYMV(Element.F32(mRS), Uplo, A, X, Y, incX, incY);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssymv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void SSBMV(@Uplo int Uplo, int K, float alpha, Allocation A, Allocation X, int incX, float beta, Allocation Y, int incY) {
+ // SBMV is the same as SYMV
+ int N = validateSYMV(Element.F32(mRS), Uplo, A, X, Y, incX, incY);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void SSPMV(@Uplo int Uplo, float alpha, Allocation Ap, Allocation X, int incX, float beta, Allocation Y, int incY) {
+ int N = validateSPMV(Element.F32(mRS), Uplo, Ap, X, incX, Y, incY);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, Ap.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void SGER(float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sger, 0, 0, 0, 0, 0, M, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0.f, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void SSYR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation A) {
+ int N = validateSYR(Element.F32(mRS), Uplo, X, incX, A);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), A.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+ }
+ void SSPR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Ap) {
+ int N = validateSPR(Element.F32(mRS), Uplo, X, incX, Ap);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Ap.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+ }
+ void SSYR2(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ int N = validateSYR2(Element.F32(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void SSPR2(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+ int N = validateSPR2(Element.F32(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sspr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, Ap.getID(mRS), incX, incY, 0, 0);
+ }
+ void DSYMV(@Uplo int Uplo, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+ int N = validateSYMV(Element.F64(mRS), Uplo, A, X, Y, incX, incY);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsymv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void DSBMV(@Uplo int Uplo, int K, double alpha, Allocation A, Allocation X, int incX, double beta, Allocation Y, int incY) {
+ // SBMV is the same as SYMV
+ int N = validateSYMV(Element.F64(mRS), Uplo, A, X, Y, incX, incY);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha, A.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void DSPMV(@Uplo int Uplo, double alpha, Allocation Ap, Allocation X, int incX, double beta, Allocation Y, int incY) {
+ int N = validateSPMV(Element.F64(mRS), Uplo, Ap, X, incX, Y, incY);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, Ap.getID(mRS), X.getID(mRS), beta, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void DGER(double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dger, 0, 0, 0, 0, 0, M, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0.f, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void DSYR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation A) {
+ int N = validateSYR(Element.F64(mRS), Uplo, X, incX, A);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), A.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+ }
+ void DSPR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Ap) {
+ int N = validateSPR(Element.F64(mRS), Uplo, X, incX, Ap);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Ap.getID(mRS), 0.f, 0, incX, 0, 0, 0);
+ }
+ void DSYR2(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ int N = validateSYR2(Element.F64(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void DSPR2(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+ int N = validateSPR2(Element.F64(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dspr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, X.getID(mRS), Y.getID(mRS), 0, Ap.getID(mRS), incX, incY, 0, 0);
+ }
+
+
+ /**
+ * Level 2, C and Z only
+ */
+
+ static void validateGERU(Element e, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ if (!A.getType().getElement().isCompatible(e) ||
+ !X.getType().getElement().isCompatible(e) ||
+ !Y.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (X.getType().getY() > 1 || Y.getType().getY() > 1) {
+ throw new RSRuntimeException("BLAS vectors must have Y dimension of 0 or 1");
+ }
+
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+
+ int expectedXDim = 1 + (N - 1) * incX;
+ if (X.getType().getX() != expectedXDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for GERU");
+ }
+ int expectedYDim = 1 + (N - 1) * incY;
+ if (Y.getType().getX() != expectedYDim) {
+ throw new RSRuntimeException("Incorrect vector dimensions for GERU");
+ }
+
+ }
+
+ void CHEMV(@Uplo int Uplo, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+ // HEMV is the same as SYR2 validation-wise
+ int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chemv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void CHBMV(@Uplo int Uplo, int K, Float2 alpha, Allocation A, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+ // HBMV is the same as SYR2 validation-wise
+ int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+ if (K < 0) {
+ throw new RSRuntimeException("K must be 0 or greater for HBMV");
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void CHPMV(@Uplo int Uplo, Float2 alpha, Allocation Ap, Allocation X, int incX, Float2 beta, Allocation Y, int incY) {
+ // HPMV is the same as SPR2
+ int N = validateSPR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, Ap.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void CGERU(Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ validateGERU(Element.F32_2(mRS), X, incX, Y, incY, A);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgeru, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void CGERC(Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ // same as GERU
+ validateGERU(Element.F32_2(mRS), X, incX, Y, incY, A);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgerc, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void CHER(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation A) {
+ // same as SYR
+ int N = validateSYR(Element.F32(mRS), Uplo, X, incX, A);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, A.getID(mRS), incX, 0, 0, 0);
+ }
+ void CHPR(@Uplo int Uplo, float alpha, Allocation X, int incX, Allocation Ap) {
+ // equivalent to SPR for validation
+ int N = validateSPR(Element.F32_2(mRS), Uplo, X, incX, Ap);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, Ap.getID(mRS), incX, 0, 0, 0);
+ }
+ void CHER2(@Uplo int Uplo, Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ // same as SYR2
+ int N = validateSYR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void CHPR2(@Uplo int Uplo, Float2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+ // same as SPR2
+ int N = validateSPR2(Element.F32_2(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chpr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, Ap.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZHEMV(@Uplo int Uplo, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+ // HEMV is the same as SYR2 validation-wise
+ int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhemv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZHBMV(@Uplo int Uplo, int K, Double2 alpha, Allocation A, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+ // HBMV is the same as SYR2 validation-wise
+ int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+ if (K < 0) {
+ throw new RSRuntimeException("K must be 0 or greater for HBMV");
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhbmv, 0, 0, 0, Uplo, 0, 0, N, K, alpha.x, alpha.y, A.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZHPMV(@Uplo int Uplo, Double2 alpha, Allocation Ap, Allocation X, int incX, Double2 beta, Allocation Y, int incY) {
+ // HPMV is the same as SPR2
+ int N = validateSPR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpmv, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, Ap.getID(mRS), X.getID(mRS), beta.x, beta.y, Y.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZGERU(Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ validateGERU(Element.F64_2(mRS), X, incX, Y, incY, A);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgeru, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZGERC(Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ // same as GERU
+ validateGERU(Element.F64_2(mRS), X, incX, Y, incY, A);
+ int M = A.getType().getY();
+ int N = A.getType().getX();
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgerc, 0, 0, 0, 0, 0, M, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZHER(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation A) {
+ // same as SYR
+ int N = validateSYR(Element.F64(mRS), Uplo, X, incX, A);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, A.getID(mRS), incX, 0, 0, 0);
+ }
+ void ZHPR(@Uplo int Uplo, double alpha, Allocation X, int incX, Allocation Ap) {
+ // equivalent to SPR for validation
+ int N = validateSPR(Element.F64_2(mRS), Uplo, X, incX, Ap);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpr, 0, 0, 0, Uplo, 0, 0, N, 0, alpha, 0, X.getID(mRS), 0, 0, 0, Ap.getID(mRS), incX, 0, 0, 0);
+ }
+ void ZHER2(@Uplo int Uplo, Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation A) {
+ // same as SYR2
+ int N = validateSYR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, A);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, A.getID(mRS), incX, incY, 0, 0);
+ }
+ void ZHPR2(@Uplo int Uplo, Double2 alpha, Allocation X, int incX, Allocation Y, int incY, Allocation Ap) {
+ // same as SPR2
+ int N = validateSPR2(Element.F64_2(mRS), Uplo, X, incX, Y, incY, Ap);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhpr2, 0, 0, 0, Uplo, 0, 0, N, 0, alpha.x, alpha.y, X.getID(mRS), Y.getID(mRS), 0, 0, Ap.getID(mRS), incX, incY, 0, 0);
+ }
+
+
+ /**
+ * Level 3 BLAS
+ */
+
+ static void validateL3(Element e, int TransA, int TransB, int Side, Allocation A, Allocation B, Allocation C) {
+ int aX = -1, aY = -1, bX = -1, bY = -1, cX = -1, cY = -1;
+ if ((A != null && !A.getType().getElement().isCompatible(e)) ||
+ (B != null && !B.getType().getElement().isCompatible(e)) ||
+ (C != null && !C.getType().getElement().isCompatible(e))) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (C != null) {
+ cX = C.getType().getY();
+ cY = C.getType().getX();
+ }
+ if (Side == RIGHT) {
+ if (B != null) {
+ bX = A.getType().getY();
+ bY = A.getType().getX();
+ }
+ if (A != null) {
+ aX = B.getType().getY();
+ aY = B.getType().getX();
+ }
+ } else {
+ if (A != null) {
+ if (TransA == TRANSPOSE) {
+ aY = A.getType().getY();
+ aX = A.getType().getX();
+ } else {
+ aX = A.getType().getY();
+ aY = A.getType().getX();
+ }
+ }
+ if (B != null) {
+ if (TransB == TRANSPOSE) {
+ bY = B.getType().getY();
+ bX = B.getType().getX();
+ } else {
+ bX = B.getType().getY();
+ bY = B.getType().getX();
+ }
+ }
+ }
+ if (A != null && B != null && C != null) {
+ if (aY != bX || aX != cX || bY != cY) {
+ throw new RSRuntimeException("Called BLAS with invalid dimensions");
+ }
+ } else if (A != null && C != null) {
+ // A and C only
+ if (aX != cY || aY != cX) {
+ throw new RSRuntimeException("Called BLAS with invalid dimensions");
+ }
+ } else if (A != null && B != null) {
+ // A and B only
+ }
+
+ }
+
+ public void SGEMM(@Transpose int TransA, @Transpose int TransB, float alpha, Allocation A,
+ Allocation B, float beta, Allocation C) {
+ validateTranspose(TransA);
+ validateTranspose(TransB);
+ validateL3(Element.F32(mRS), TransA, TransB, 0, A, B, C);
+
+ int M = -1, N = -1, K = -1;
+ if (TransA == TRANSPOSE) {
+ M = A.getType().getX();
+ K = A.getType().getY();
+ } else {
+ M = A.getType().getY();
+ K = A.getType().getX();
+ }
+ if (TransB == TRANSPOSE) {
+ N = B.getType().getY();
+ } else {
+ N = B.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_sgemm, TransA, TransB, 0, 0, 0, M, N, K, alpha, A.getID(mRS), B.getID(mRS),
+ beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void DGEMM(@Transpose int TransA, @Transpose int TransB, double alpha, Allocation A,
+ Allocation B, double beta, Allocation C) {
+ validateTranspose(TransA);
+ validateTranspose(TransB);
+ validateL3(Element.F64(mRS), TransA, TransB, 0, A, B, C);
+ int M = -1, N = -1, K = -1;
+ if (TransA == TRANSPOSE) {
+ M = A.getType().getX();
+ K = A.getType().getY();
+ } else {
+ M = A.getType().getY();
+ K = A.getType().getX();
+ }
+ if (TransB == TRANSPOSE) {
+ N = B.getType().getY();
+ } else {
+ N = B.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dgemm, TransA, TransB, 0, 0, 0, M, N, K, alpha, A.getID(mRS), B.getID(mRS),
+ beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void CGEMM(@Transpose int TransA, @Transpose int TransB, Float2 alpha, Allocation A,
+ Allocation B, Float2 beta, Allocation C) {
+ validateTranspose(TransA);
+ validateTranspose(TransB);
+ validateL3(Element.F32_2(mRS), TransA, TransB, 0, A, B, C);
+ int M = -1, N = -1, K = -1;
+ if (TransA == TRANSPOSE) {
+ M = A.getType().getX();
+ K = A.getType().getY();
+ } else {
+ M = A.getType().getY();
+ K = A.getType().getX();
+ }
+ if (TransB == TRANSPOSE) {
+ N = B.getType().getY();
+ } else {
+ N = B.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cgemm, TransA, TransB, 0, 0, 0, M, N, K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+ beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ public void ZGEMM(@Transpose int TransA, @Transpose int TransB, Double2 alpha, Allocation A,
+ Allocation B, Double2 beta, Allocation C) {
+ validateTranspose(TransA);
+ validateTranspose(TransB);
+ validateL3(Element.F64_2(mRS), TransA, TransB, 0, A, B, C);
+ int M = -1, N = -1, K = -1;
+ if (TransA == TRANSPOSE) {
+ M = A.getType().getX();
+ K = A.getType().getY();
+ } else {
+ M = A.getType().getY();
+ K = A.getType().getX();
+ }
+ if (TransB == TRANSPOSE) {
+ N = B.getType().getY();
+ } else {
+ N = B.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zgemm, TransA, TransB, 0, 0, 0, M, N, K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+ beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ public void SSYMM(@Side int Side, @Uplo int Uplo, float alpha, Allocation A,
+ Allocation B, float beta, Allocation C) {
+ validateSide(Side);
+ validateUplo(Uplo);
+ validateL3(Element.F32(mRS), 0, 0, Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha, A.getID(mRS), B.getID(mRS),
+ beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void DSYMM(@Side int Side, @Uplo int Uplo, double alpha, Allocation A,
+ Allocation B, double beta, Allocation C) {
+ validateSide(Side);
+ validateUplo(Uplo);
+ validateL3(Element.F64(mRS), 0, 0, Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha, A.getID(mRS), B.getID(mRS),
+ beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void CSYMM(@Side int Side, @Uplo int Uplo, Float2 alpha, Allocation A,
+ Allocation B, Float2 beta, Allocation C) {
+ validateSide(Side);
+ validateUplo(Uplo);
+ validateL3(Element.F32_2(mRS), 0, 0, Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+ beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZSYMM(@Side int Side, @Uplo int Uplo, Double2 alpha, Allocation A,
+ Allocation B, Double2 beta, Allocation C) {
+ validateSide(Side);
+ validateUplo(Uplo);
+ validateL3(Element.F64_2(mRS), 0, 0, Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsymm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS),
+ beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ public void SSYRK(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, float beta, Allocation C) {
+ validateTranspose(Trans);
+ validateUplo(Uplo);
+ validateL3(Element.F32(mRS), Trans, 0, 0, A, null, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), 0, beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ public void DSYRK(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, double beta, Allocation C) {
+ validateTranspose(Trans);
+ validateUplo(Uplo);
+ validateL3(Element.F64(mRS), Trans, 0, 0, A, null, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_dsyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), 0, beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void CSYRK(@Uplo int Uplo, @Transpose int Trans, float alphaX, float alphaY, Allocation A, float betaX, float betaY, Allocation C) {
+ validateTranspose(Trans);
+ validateUplo(Uplo);
+ validateL3(Element.F32_2(mRS), Trans, 0, 0, A, null, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_csyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alphaX, alphaY, A.getID(mRS), 0, betaX, betaY,
+ C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZSYRK(@Uplo int Uplo, @Transpose int Trans, double alphaX, double alphaY, Allocation A, double betaX, double betaY, Allocation C) {
+ validateTranspose(Trans);
+ validateUplo(Uplo);
+ validateL3(Element.F64_2(mRS), Trans, 0, 0, A, null, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zsyrk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alphaX, alphaY, A.getID(mRS), 0, betaX, betaY,
+ C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ static void validateSYR2K(Element e, @Transpose int Trans, Allocation A, Allocation B, Allocation C) {
+ validateTranspose(Trans);
+ if (!A.getType().getElement().isCompatible(e) ||
+ !B.getType().getElement().isCompatible(e) ||
+ !C.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ int Cdim = -1;
+ // A is n x k if no transpose, k x n if transpose
+ // C is n x n
+ if (Trans == TRANSPOSE) {
+ // check columns versus C
+ Cdim = A.getType().getX();
+ } else {
+ // check rows versus C
+ Cdim = A.getType().getY();
+ }
+ if (C.getType().getX() != Cdim && C.getType().getY() != Cdim) {
+ throw new RSRuntimeException("Invalid symmetric matrix in SYR2K");
+ }
+ // A dims == B dims
+ if (A.getType().getX() != B.getType().getX() || A.getType().getY() != B.getType().getY()) {
+ throw new RSRuntimeException("Invalid A and B in SYR2K");
+ }
+ }
+ public void SSYR2K(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, Allocation B, float beta, Allocation C) {
+ validateUplo(Uplo);
+ validateSYR2K(Element.F32(mRS), Trans, A, B, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void DSYR2K(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, Allocation B, double beta, Allocation C) {
+ validateUplo(Uplo);
+ validateSYR2K(Element.F64(mRS), Trans, A, B, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha, A.getID(mRS), B.getID(mRS), beta, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void CSYR2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, Float2 beta, Allocation C) {
+ validateUplo(Uplo);
+ validateSYR2K(Element.F32_2(mRS), Trans, A, B, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZSYR2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, Double2 beta, Allocation C) {
+ validateUplo(Uplo);
+ validateSYR2K(Element.F64_2(mRS), Trans, A, B, C);
+ int K = -1;
+ if (Trans == TRANSPOSE) {
+ K = A.getType().getY();
+ } else {
+ K = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_ssyr2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), K, alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), beta.x, beta.y, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ static void validateTRMM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
+ validateSide(Side);
+ validateTranspose(TransA);
+ int aX = -1, aY = -1, bX = -1, bY = -1;
+ if (!A.getType().getElement().isCompatible(e) ||
+ !B.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ if (TransA == TRANSPOSE) {
+ aY = A.getType().getY();
+ aX = A.getType().getX();
+ } else {
+ aY = A.getType().getX();
+ aX = A.getType().getY();
+ }
+ bX = B.getType().getY();
+ bY = B.getType().getX();
+ if (Side == LEFT) {
+ if (aX == 0 || aY != bX) {
+ throw new RSRuntimeException("Called TRMM with invalid matrices");
+ }
+ } else {
+ if (bY != aX || aY == 0) {
+ throw new RSRuntimeException("Called TRMM with invalid matrices");
+ }
+ }
+ }
+ public void STRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, float alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRMM(Element.F32(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha, A.getID(mRS), B.getID(mRS), 0.f, 0, 0, 0, 0, 0);
+ }
+ public void DTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, double alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRMM(Element.F64(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha, A.getID(mRS), B.getID(mRS), 0.f, 0, 0, 0, 0, 0);
+ }
+ public void CTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRMM(Element.F32_2(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+ }
+ public void ZTRMM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRMM(Element.F64_2(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strmm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+ }
+
+ static void validateTRSM(Element e, @Side int Side, @Transpose int TransA, Allocation A, Allocation B) {
+ int adim = -1, bX = -1, bY = -1;
+ validateSide(Side);
+ validateTranspose(TransA);
+ if (!A.getType().getElement().isCompatible(e) ||
+ !B.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ adim = A.getType().getX();
+ if (adim != A.getType().getY()) {
+ // this may be unnecessary, the restriction could potentially be relaxed
+ // A needs to contain at least that symmetric matrix but could theoretically be larger
+ // for now we assume adapters are sufficient, will reevaluate in the future
+ throw new RSRuntimeException("Called TRSM with a non-symmetric matrix A");
+ }
+ bX = B.getType().getY();
+ bY = B.getType().getX();
+ if (Side == LEFT) {
+ // A is M*M
+ if (adim != bY) {
+ throw new RSRuntimeException("Called TRSM with invalid matrix dimensions");
+ }
+ } else {
+ // A is N*N
+ if (adim != bX) {
+ throw new RSRuntimeException("Called TRSM with invalid matrix dimensions");
+ }
+ }
+ }
+ public void STRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, float alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRSM(Element.F32(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Single(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
+ }
+ public void DTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, double alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRSM(Element.F64(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Double(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0);
+ }
+ public void CTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Float2 alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRSM(Element.F32_2(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+ }
+ public void ZTRSM(@Side int Side, @Uplo int Uplo, @Transpose int TransA, @Diag int Diag, Double2 alpha, Allocation A, Allocation B) {
+ validateUplo(Uplo);
+ validateDiag(Diag);
+ validateTRSM(Element.F64_2(mRS), Side, TransA, A, B);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_strsm, TransA, 0, Side, Uplo, Diag, B.getType().getY(), B.getType().getX(), 0,
+ alpha.x, alpha.y, A.getID(mRS), B.getID(mRS), 0, 0, 0, 0, 0, 0, 0);
+ }
+
+ static void validateHEMM(Element e, @Side int Side, Allocation A, Allocation B, Allocation C) {
+ validateSide(Side);
+
+ if (!A.getType().getElement().isCompatible(e) ||
+ !B.getType().getElement().isCompatible(e) ||
+ !C.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+
+ // A must be square; can potentially be relaxed similar to TRSM
+ int adim = A.getType().getX();
+ if (adim != A.getType().getY()) {
+ throw new RSRuntimeException("Called HEMM with non-square A");
+ }
+ if ((Side == LEFT && adim != B.getType().getY()) ||
+ (Side == RIGHT && adim != B.getType().getX())) {
+ throw new RSRuntimeException("Called HEMM with invalid B");
+ }
+ if (B.getType().getX() != C.getType().getX() ||
+ B.getType().getY() != C.getType().getY()) {
+ throw new RSRuntimeException("Called HEMM with mismatched B and C");
+ }
+ }
+ public void CHEMM(@Side int Side, @Uplo int Uplo, float alpha, Allocation A, Allocation B, float beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHEMM(Element.F32_2(mRS), Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_chemm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0,
+ alpha, 0, A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZHEMM(@Side int Side, @Uplo int Uplo, double alpha, Allocation A, Allocation B, double beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHEMM(Element.F32_2(mRS), Side, A, B, C);
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zhemm, 0, 0, Side, Uplo, 0, C.getType().getY(), C.getType().getX(), 0,
+ alpha, 0, A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ static void validateHERK(Element e, @Transpose int Trans, Allocation A, Allocation C) {
+ if (!A.getType().getElement().isCompatible(e) ||
+ !C.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ validateConjTranspose(Trans);
+ int cdim = C.getType().getX();
+ if (cdim != C.getType().getY()) {
+ throw new RSRuntimeException("Called HERK with non-square C");
+ }
+ if (Trans == NO_TRANSPOSE) {
+ if (cdim != A.getType().getX()) {
+ throw new RSRuntimeException("Called HERK with invalid A");
+ }
+ } else {
+ if (cdim != A.getType().getY()) {
+ throw new RSRuntimeException("Called HERK with invalid A");
+ }
+ }
+ }
+ public void CHERK(@Uplo int Uplo, @Transpose int Trans, float alpha, Allocation A, float beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHERK(Element.F32_2(mRS), Trans, A, C);
+ int k = 0;
+ if (Trans == TRANSPOSE) {
+ k = A.getType().getY();
+ } else {
+ k = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cherk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k,
+ alpha, 0, A.getID(mRS), 0, beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZHERK(@Uplo int Uplo, @Transpose int Trans, double alpha, Allocation A, double beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHERK(Element.F64_2(mRS), Trans, A, C);
+ int k = 0;
+ if (Trans == TRANSPOSE) {
+ k = A.getType().getY();
+ } else {
+ k = A.getType().getX();
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zherk, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k,
+ alpha, 0, A.getID(mRS), 0, beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+ static void validateHER2K(Element e, @Transpose int Trans, Allocation A, Allocation B, Allocation C) {
+ if (!A.getType().getElement().isCompatible(e) ||
+ !B.getType().getElement().isCompatible(e) ||
+ !C.getType().getElement().isCompatible(e)) {
+ throw new RSRuntimeException("Called BLAS with wrong Element type");
+ }
+ validateConjTranspose(Trans);
+ int cdim = C.getType().getX();
+ if (cdim != C.getType().getY()) {
+ throw new RSRuntimeException("Called HER2K with non-square C");
+ }
+ if (Trans == NO_TRANSPOSE) {
+ if (A.getType().getY() != cdim) {
+ throw new RSRuntimeException("Called HER2K with invalid matrices");
+ }
+ } else {
+ if (A.getType().getX() != cdim) {
+ throw new RSRuntimeException("Called HER2K with invalid matrices");
+ }
+ }
+ if (A.getType().getX() != B.getType().getX() || A.getType().getY() != B.getType().getY()) {
+ throw new RSRuntimeException("Called HER2K with invalid A and B matrices");
+ }
+ }
+ public void CHER2K(@Uplo int Uplo, @Transpose int Trans, Float2 alpha, Allocation A, Allocation B, float beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHER2K(Element.F32_2(mRS), Trans, A, B, C);
+ int k = 0;
+ if (Trans == NO_TRANSPOSE) {
+ k = A.getType().getX();
+ } else {
+ k = A.getType().getY();
+ }
+ mRS.nScriptIntrinsicBLAS_Complex(getID(mRS), RsBlas_cher2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k, alpha.x, alpha.y,
+ A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+ public void ZHER2K(@Uplo int Uplo, @Transpose int Trans, Double2 alpha, Allocation A, Allocation B, double beta, Allocation C) {
+ validateUplo(Uplo);
+ validateHER2K(Element.F64_2(mRS), Trans, A, B, C);
+ int k = 0;
+ if (Trans == NO_TRANSPOSE) {
+ k = A.getType().getX();
+ } else {
+ k = A.getType().getY();
+ }
+ mRS.nScriptIntrinsicBLAS_Z(getID(mRS), RsBlas_zher2k, Trans, 0, 0, Uplo, 0, 0, C.getType().getX(), k, alpha.x, alpha.y,
+ A.getID(mRS), B.getID(mRS), beta, 0, C.getID(mRS), 0, 0, 0, 0);
+ }
+
+
+
+}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 198cabe..2612323 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -310,6 +310,143 @@
}
static void
+nScriptIntrinsicBLAS_Single(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA,
+ jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
+ jfloat alpha, jlong A, jlong B, jfloat beta, jlong C, jint incX, jint incY,
+ jint KL, jint KU) {
+ RsBlasCall call;
+ memset(&call, 0, sizeof(call));
+ call.func = (RsBlasFunction)func;
+ call.transA = (RsBlasTranspose)TransA;
+ call.transB = (RsBlasTranspose)TransB;
+ call.side = (RsBlasSide)Side;
+ call.uplo = (RsBlasUplo)Uplo;
+ call.diag = (RsBlasDiag)Diag;
+ call.M = M;
+ call.N = N;
+ call.K = K;
+ call.alpha.f = alpha;
+ call.beta.f = beta;
+ call.incX = incX;
+ call.incY = incY;
+ call.KL = KL;
+ call.KU = KU;
+
+ RsAllocation in_allocs[3];
+ in_allocs[0] = (RsAllocation)A;
+ in_allocs[1] = (RsAllocation)B;
+ in_allocs[2] = (RsAllocation)C;
+
+ rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
+ in_allocs, sizeof(in_allocs), nullptr,
+ &call, sizeof(call), nullptr, 0);
+}
+
+static void
+nScriptIntrinsicBLAS_Double(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA,
+ jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
+ jdouble alpha, jlong A, jlong B, jdouble beta, jlong C, jint incX, jint incY,
+ jint KL, jint KU) {
+ RsBlasCall call;
+ memset(&call, 0, sizeof(call));
+ call.func = (RsBlasFunction)func;
+ call.transA = (RsBlasTranspose)TransA;
+ call.transB = (RsBlasTranspose)TransB;
+ call.side = (RsBlasSide)Side;
+ call.uplo = (RsBlasUplo)Uplo;
+ call.diag = (RsBlasDiag)Diag;
+ call.M = M;
+ call.N = N;
+ call.K = K;
+ call.alpha.d = alpha;
+ call.beta.d = beta;
+ call.incX = incX;
+ call.incY = incY;
+ call.KL = KL;
+ call.KU = KU;
+
+ RsAllocation in_allocs[3];
+ in_allocs[0] = (RsAllocation)A;
+ in_allocs[1] = (RsAllocation)B;
+ in_allocs[2] = (RsAllocation)C;
+
+ rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
+ in_allocs, sizeof(in_allocs), nullptr,
+ &call, sizeof(call), nullptr, 0);
+}
+
+static void
+nScriptIntrinsicBLAS_Complex(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA,
+ jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
+ jfloat alphaX, jfloat alphaY, jlong A, jlong B, jfloat betaX,
+ jfloat betaY, jlong C, jint incX, jint incY, jint KL, jint KU) {
+ RsBlasCall call;
+ memset(&call, 0, sizeof(call));
+ call.func = (RsBlasFunction)func;
+ call.transA = (RsBlasTranspose)TransA;
+ call.transB = (RsBlasTranspose)TransB;
+ call.side = (RsBlasSide)Side;
+ call.uplo = (RsBlasUplo)Uplo;
+ call.diag = (RsBlasDiag)Diag;
+ call.M = M;
+ call.N = N;
+ call.K = K;
+ call.alpha.c.r = alphaX;
+ call.alpha.c.i = alphaY;
+ call.beta.c.r = betaX;
+ call.beta.c.r = betaY;
+ call.incX = incX;
+ call.incY = incY;
+ call.KL = KL;
+ call.KU = KU;
+
+ RsAllocation in_allocs[3];
+ in_allocs[0] = (RsAllocation)A;
+ in_allocs[1] = (RsAllocation)B;
+ in_allocs[2] = (RsAllocation)C;
+
+ rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
+ in_allocs, sizeof(in_allocs), nullptr,
+ &call, sizeof(call), nullptr, 0);
+}
+
+static void
+nScriptIntrinsicBLAS_Z(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA,
+ jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K,
+ jdouble alphaX, jdouble alphaY, jlong A, jlong B, jdouble betaX,
+ jdouble betaY, jlong C, jint incX, jint incY, jint KL, jint KU) {
+ RsBlasCall call;
+ memset(&call, 0, sizeof(call));
+ call.func = (RsBlasFunction)func;
+ call.transA = (RsBlasTranspose)TransA;
+ call.transB = (RsBlasTranspose)TransB;
+ call.side = (RsBlasSide)Side;
+ call.uplo = (RsBlasUplo)Uplo;
+ call.diag = (RsBlasDiag)Diag;
+ call.M = M;
+ call.N = N;
+ call.K = K;
+ call.alpha.z.r = alphaX;
+ call.alpha.z.i = alphaY;
+ call.beta.z.r = betaX;
+ call.beta.z.r = betaY;
+ call.incX = incX;
+ call.incY = incY;
+ call.KL = KL;
+ call.KU = KU;
+
+ RsAllocation in_allocs[3];
+ in_allocs[0] = (RsAllocation)A;
+ in_allocs[1] = (RsAllocation)B;
+ in_allocs[2] = (RsAllocation)C;
+
+ rsScriptForEachMulti((RsContext)con, (RsScript)id, 0,
+ in_allocs, sizeof(in_allocs), nullptr,
+ &call, sizeof(call), nullptr, 0);
+}
+
+
+static void
nAssignName(JNIEnv *_env, jobject _this, jlong con, jlong obj, jbyteArray str)
{
if (kLogApi) {
@@ -2094,6 +2231,11 @@
{"rsnScriptGroupExecute", "(JJ)V", (void*)nScriptGroupExecute },
{"rsnScriptGroup2Execute", "(JJ)V", (void*)nScriptGroup2Execute },
+{"rsnScriptIntrinsicBLAS_Single", "(JJIIIIIIIIIFJJFJIIII)V", (void*)nScriptIntrinsicBLAS_Single },
+{"rsnScriptIntrinsicBLAS_Double", "(JJIIIIIIIIIDJJDJIIII)V", (void*)nScriptIntrinsicBLAS_Double },
+{"rsnScriptIntrinsicBLAS_Complex", "(JJIIIIIIIIIFFJJFFJIIII)V", (void*)nScriptIntrinsicBLAS_Complex },
+{"rsnScriptIntrinsicBLAS_Z", "(JJIIIIIIIIIDDJJDDJIIII)V", (void*)nScriptIntrinsicBLAS_Z },
+
{"rsnProgramStoreCreate", "(JZZZZZZIII)J", (void*)nProgramStoreCreate },
{"rsnProgramBindConstants", "(JJIJ)V", (void*)nProgramBindConstants },
diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
index c8b080e..b4613d6 100644
--- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -34,6 +34,7 @@
import android.text.TextUtils;
import android.util.Property;
import android.util.Slog;
+import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MagnificationSpec;
@@ -110,7 +111,6 @@
private static final int STATE_MAGNIFIED_INTERACTION = 4;
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
- private static final int MULTI_TAP_TIME_SLOP_ADJUSTMENT = 50;
private static final int MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED = 1;
private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 2;
@@ -135,9 +135,8 @@
private final AccessibilityManagerService mAms;
- private final int mTapTimeSlop = ViewConfiguration.getTapTimeout();
- private final int mMultiTapTimeSlop =
- ViewConfiguration.getDoubleTapTimeout() - MULTI_TAP_TIME_SLOP_ADJUSTMENT;
+ private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout();
+ private final int mMultiTapTimeSlop;
private final int mTapDistanceSlop;
private final int mMultiTapDistanceSlop;
@@ -192,6 +191,9 @@
mWindowManager = LocalServices.getService(WindowManagerInternal.class);
mAms = service;
+ mMultiTapTimeSlop = ViewConfiguration.getDoubleTapTimeout()
+ + mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment);
mLongAnimationDuration = context.getResources().getInteger(
com.android.internal.R.integer.config_longAnimTime);
mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -481,15 +483,20 @@
private static final float MIN_SCALE = 1.3f;
private static final float MAX_SCALE = 5.0f;
- private static final float SCALING_THRESHOLD = 0.3f;
-
private final ScaleGestureDetector mScaleGestureDetector;
private final GestureDetector mGestureDetector;
+ private final float mScalingThreshold;
+
private float mInitialScaleFactor = -1;
private boolean mScaling;
public MagnifiedContentInteractonStateHandler(Context context) {
+ final TypedValue scaleValue = new TypedValue();
+ context.getResources().getValue(
+ com.android.internal.R.dimen.config_screen_magnification_scaling_threshold,
+ scaleValue, false);
+ mScalingThreshold = scaleValue.getFloat();
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScaleGestureDetector.setQuickScaleEnabled(false);
mGestureDetector = new GestureDetector(context, this);
@@ -537,7 +544,7 @@
mInitialScaleFactor = detector.getScaleFactor();
} else {
final float deltaScale = detector.getScaleFactor() - mInitialScaleFactor;
- if (Math.abs(deltaScale) > SCALING_THRESHOLD) {
+ if (Math.abs(deltaScale) > mScalingThreshold) {
mScaling = true;
return true;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7623514..da11dad 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2837,10 +2837,10 @@
return providersUpdated;
}
- private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) {
+ private boolean removeProvidersForPackageLocked(String pkgName, int userId) {
boolean removed = false;
- int N = mProviders.size();
+ final int N = mProviders.size();
for (int i = N - 1; i >= 0; i--) {
Provider provider = mProviders.get(i);
if (pkgName.equals(provider.info.provider.getPackageName())
@@ -2849,11 +2849,16 @@
removed = true;
}
}
+ return removed;
+ }
+
+ private boolean removeHostsAndProvidersForPackageLocked(String pkgName, int userId) {
+ boolean removed = removeProvidersForPackageLocked(pkgName, userId);
// Delete the hosts for this package too
// By now, we have removed any AppWidgets that were in any hosts here,
// so we don't need to worry about sending DISABLE broadcasts to them.
- N = mHosts.size();
+ final int N = mHosts.size();
for (int i = N - 1; i >= 0; i--) {
Host host = mHosts.get(i);
if (pkgName.equals(host.id.packageName)
@@ -2925,13 +2930,30 @@
synchronized (mLock) {
boolean providersChanged = false;
+ ArraySet<String> previousPackages = new ArraySet<String>();
+ final int providerCount = mProviders.size();
+ for (int i = 0; i < providerCount; ++i) {
+ Provider provider = mProviders.get(i);
+ if (provider.getUserId() == userId) {
+ previousPackages.add(provider.id.componentName.getPackageName());
+ }
+ }
+
final int packageCount = packages.size();
for (int i = 0; i < packageCount; i++) {
String packageName = packages.get(i);
+ previousPackages.remove(packageName);
providersChanged |= updateProvidersForPackageLocked(packageName,
userId, null);
}
+ // Some packages are no longer whitelisted.
+ final int removedCount = previousPackages.size();
+ for (int i = 0; i < removedCount; ++i) {
+ providersChanged |= removeProvidersForPackageLocked(
+ previousPackages.valueAt(i), userId);
+ }
+
if (providersChanged) {
saveGroupStateAsync(userId);
scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
@@ -3142,10 +3164,10 @@
if (parentId != callerId) {
return false;
}
- return isProviderWhitelListed(packageName, profileId);
+ return isProviderWhiteListed(packageName, profileId);
}
- public boolean isProviderWhitelListed(String packageName, int profileId) {
+ public boolean isProviderWhiteListed(String packageName, int profileId) {
DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
DevicePolicyManagerInternal.class);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 4d7ebed..acf4d39 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2778,7 +2778,22 @@
@Override
public void operationComplete() {
- // Okay, the agent successfully reported back to us!
+ // The agent reported back to us!
+
+ if (mBackupData == null) {
+ // This callback was racing with our timeout, so we've cleaned up the
+ // agent state already and are on to the next thing. We have nothing
+ // further to do here: agent state having been cleared means that we've
+ // initiated the appropriate next operation.
+ final String pkg = (mCurrentPackage != null)
+ ? mCurrentPackage.packageName : "[none]";
+ if (DEBUG) {
+ Slog.i(TAG, "Callback after agent teardown: " + pkg);
+ }
+ addBackupTrace("late opComplete; curPkg = " + pkg);
+ return;
+ }
+
final String pkgName = mCurrentPackage.packageName;
final long filepos = mBackupDataName.length();
FileDescriptor fd = mBackupData.getFileDescriptor();
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 8bd7132..2e84fbe 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -318,6 +318,8 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
+
BackupManagerService svc = mService;
if (svc != null) {
svc.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 912a181..b3b4651 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -626,6 +626,22 @@
pw.println(" voltage: " + mBatteryProps.batteryVoltage);
pw.println(" temperature: " + mBatteryProps.batteryTemperature);
pw.println(" technology: " + mBatteryProps.batteryTechnology);
+
+ } else if ("unplug".equals(args[0])) {
+ if (!mUpdatesStopped) {
+ mLastBatteryProps.set(mBatteryProps);
+ }
+ mBatteryProps.chargerAcOnline = false;
+ mBatteryProps.chargerUsbOnline = false;
+ mBatteryProps.chargerWirelessOnline = false;
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUpdatesStopped = true;
+ processValuesLocked(false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
} else if (args.length == 3 && "set".equals(args[0])) {
String key = args[1];
String value = args[2];
@@ -662,6 +678,7 @@
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
}
+
} else if (args.length == 1 && "reset".equals(args[0])) {
long ident = Binder.clearCallingIdentity();
try {
@@ -676,6 +693,7 @@
} else {
pw.println("Dump current battery state, or:");
pw.println(" set [ac|usb|wireless|status|level|invalid] <value>");
+ pw.println(" unplug");
pw.println(" reset");
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 551a5dc..b72b29d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2636,9 +2636,15 @@
// 100 percent is full good, 0 is full bad.
public void reportInetCondition(int networkType, int percentage) {
- if (percentage > 50) return; // don't handle good network reports
NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
- if (nai != null) reportBadNetwork(nai.network);
+ if (nai == null) return;
+ boolean isGood = percentage > 50;
+ // Revalidate if the app report does not match our current validated state.
+ if (isGood != nai.lastValidated) {
+ // Make the message logged by reportBadNetwork below less confusing.
+ if (DBG && isGood) log("reportInetCondition: type=" + networkType + " ok, revalidate");
+ reportBadNetwork(nai.network);
+ }
}
public void reportBadNetwork(Network network) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 77b8b31..c189fea 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.admin.DevicePolicyManager;
+import android.app.backup.BackupManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -46,6 +47,7 @@
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
@@ -226,6 +228,7 @@
private final void checkReadPermission(String requestedKey, int userId) {
final int callingUid = Binder.getCallingUid();
+
for (int i = 0; i < READ_PROFILE_PROTECTED_SETTINGS.length; i++) {
String key = READ_PROFILE_PROTECTED_SETTINGS[i];
if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(READ_PROFILE)
@@ -235,6 +238,16 @@
+ requestedKey + " for user " + userId);
}
}
+
+ for (int i = 0; i < READ_PASSWORD_PROTECTED_SETTINGS.length; i++) {
+ String key = READ_PASSWORD_PROTECTED_SETTINGS[i];
+ if (key.equals(requestedKey) && mContext.checkCallingOrSelfPermission(PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("uid=" + callingUid
+ + " needs permission " + PERMISSION + " to read "
+ + requestedKey + " for user " + userId);
+ }
+ }
}
@Override
@@ -257,6 +270,9 @@
private void setStringUnchecked(String key, int userId, String value) {
mStorage.writeKeyValue(key, value, userId);
+ if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) {
+ BackupManager.dataChanged("com.android.providers.settings");
+ }
}
@Override
@@ -457,12 +473,23 @@
Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
};
- // These are protected with a read permission
+ // Reading these settings needs the profile permission
private static final String[] READ_PROFILE_PROTECTED_SETTINGS = new String[] {
Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
Secure.LOCK_SCREEN_OWNER_INFO
};
+ // Reading these settings needs the same permission as checking the password
+ private static final String[] READ_PASSWORD_PROTECTED_SETTINGS = new String[] {
+ LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
+ LockPatternUtils.PASSWORD_HISTORY_KEY,
+ };
+
+ private static final String[] SETTINGS_TO_BACKUP = new String[] {
+ Secure.LOCK_SCREEN_OWNER_INFO_ENABLED,
+ Secure.LOCK_SCREEN_OWNER_INFO
+ };
+
private IMountService getMountService() {
final IBinder service = ServiceManager.getService("mount");
if (service != null) {
diff --git a/services/core/java/com/android/server/MidiService.java b/services/core/java/com/android/server/MidiService.java
index 38f1cb8..04911fa 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/core/java/com/android/server/MidiService.java
@@ -17,10 +17,10 @@
package com.android.server;
import android.content.Context;
-import android.midi.IMidiDeviceServer;
-import android.midi.IMidiListener;
-import android.midi.IMidiManager;
-import android.midi.MidiDeviceInfo;
+import android.media.midi.IMidiDeviceServer;
+import android.media.midi.IMidiListener;
+import android.media.midi.IMidiManager;
+import android.media.midi.MidiDeviceInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 1405fc1..1e3b46b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -892,11 +892,6 @@
// Temporary workaround for http://b/17945169.
Slog.d(TAG, "Setting system properties to " + systemLocale + " from mount service");
SystemProperties.set("persist.sys.locale", locale.toLanguageTag());
-
- // TODO: Stop setting these properties once we've removed all
- // references to them.
- SystemProperties.set("persist.sys.language", locale.getLanguage());
- SystemProperties.set("persist.sys.country", locale.getCountry());
}
/**
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index d1b4569..aeacd45 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -31,6 +31,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Handler;
@@ -63,7 +64,7 @@
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
- int mNightMode = UiModeManager.MODE_NIGHT_NO;
+ private int mNightMode = UiModeManager.MODE_NIGHT_NO;
private boolean mCarModeEnabled = false;
private boolean mCharging = false;
@@ -157,6 +158,7 @@
public void onStart() {
final Context context = getContext();
mTwilightManager = getLocalService(TwilightManager.class);
+
final PowerManager powerManager =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
@@ -168,20 +170,23 @@
mConfiguration.setToDefaults();
- mDefaultUiModeType = context.getResources().getInteger(
+ final Resources res = context.getResources();
+ mDefaultUiModeType = res.getInteger(
com.android.internal.R.integer.config_defaultUiModeType);
- mCarModeKeepsScreenOn = (context.getResources().getInteger(
+ mCarModeKeepsScreenOn = (res.getInteger(
com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
- mDeskModeKeepsScreenOn = (context.getResources().getInteger(
+ mDeskModeKeepsScreenOn = (res.getInteger(
com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
- mTelevision = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEVISION) ||
- context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LEANBACK);
- mWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ final PackageManager pm = context.getPackageManager();
+ mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
+ || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+
+ final int defaultNightMode = res.getInteger(
+ com.android.internal.R.integer.config_defaultNightMode);
mNightMode = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
+ Settings.Secure.UI_NIGHT_MODE, defaultNightMode);
mTwilightManager.registerListener(mTwilightListener, mHandler);
@@ -245,7 +250,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- if (isDoingNightModeLocked() && mNightMode != mode) {
+ if (mNightMode != mode) {
Settings.Secure.putInt(getContext().getContentResolver(),
Settings.Secure.UI_NIGHT_MODE, mode);
mNightMode = mode;
@@ -309,10 +314,6 @@
}
}
- boolean isDoingNightModeLocked() {
- return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
- }
-
void setCarModeLocked(boolean enabled, int flags) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
@@ -354,17 +355,13 @@
} else if (isDeskDockState(mDockState)) {
uiMode = Configuration.UI_MODE_TYPE_DESK;
}
- if (mCarModeEnabled) {
- if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
- updateComputedNightModeLocked();
- uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
- : Configuration.UI_MODE_NIGHT_NO;
- } else {
- uiMode |= mNightMode << 4;
- }
+
+ if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+ updateComputedNightModeLocked();
+ uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
+ : Configuration.UI_MODE_NIGHT_NO;
} else {
- // Disabling the car mode clears the night mode.
- uiMode = (uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | Configuration.UI_MODE_NIGHT_NO;
+ uiMode |= mNightMode << 4;
}
if (LOG) {
@@ -618,7 +615,7 @@
void updateTwilight() {
synchronized (mLock) {
- if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
+ if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
updateComputedNightModeLocked();
updateLocked(0, 0);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c267eae..966dc88 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -57,6 +57,7 @@
import android.util.ArraySet;
import android.util.SparseIntArray;
+import android.view.Display;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
@@ -65,6 +66,7 @@
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.Zygote;
@@ -439,23 +441,28 @@
public final Bundle extras;
public final Intent intent;
public final String hint;
+ public final IResultReceiver receiver;
public final int userHandle;
public boolean haveResult = false;
public Bundle result = null;
public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
- String _hint, int _userHandle) {
+ String _hint, IResultReceiver _receiver, int _userHandle) {
activity = _activity;
extras = _extras;
intent = _intent;
hint = _hint;
+ receiver = _receiver;
userHandle = _userHandle;
}
@Override
public void run() {
Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity);
- synchronized (this) {
- haveResult = true;
- notifyAll();
+ synchronized (ActivityManagerService.this) {
+ synchronized (this) {
+ haveResult = true;
+ notifyAll();
+ }
+ pendingAssistExtrasTimedOutLocked(this);
}
}
}
@@ -2249,31 +2256,33 @@
if (MONITOR_CPU_USAGE &&
mLastCpuTime.get() < (now-MONITOR_CPU_MIN_TIME)) {
mLastCpuTime.set(now);
- haveNewCpuStats = true;
mProcessCpuTracker.update();
- //Slog.i(TAG, mProcessCpu.printCurrentState());
- //Slog.i(TAG, "Total CPU usage: "
- // + mProcessCpu.getTotalCpuPercent() + "%");
+ if (mProcessCpuTracker.hasGoodLastStats()) {
+ haveNewCpuStats = true;
+ //Slog.i(TAG, mProcessCpu.printCurrentState());
+ //Slog.i(TAG, "Total CPU usage: "
+ // + mProcessCpu.getTotalCpuPercent() + "%");
- // Slog the cpu usage if the property is set.
- if ("true".equals(SystemProperties.get("events.cpu"))) {
- int user = mProcessCpuTracker.getLastUserTime();
- int system = mProcessCpuTracker.getLastSystemTime();
- int iowait = mProcessCpuTracker.getLastIoWaitTime();
- int irq = mProcessCpuTracker.getLastIrqTime();
- int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
- int idle = mProcessCpuTracker.getLastIdleTime();
+ // Slog the cpu usage if the property is set.
+ if ("true".equals(SystemProperties.get("events.cpu"))) {
+ int user = mProcessCpuTracker.getLastUserTime();
+ int system = mProcessCpuTracker.getLastSystemTime();
+ int iowait = mProcessCpuTracker.getLastIoWaitTime();
+ int irq = mProcessCpuTracker.getLastIrqTime();
+ int softIrq = mProcessCpuTracker.getLastSoftIrqTime();
+ int idle = mProcessCpuTracker.getLastIdleTime();
- int total = user + system + iowait + irq + softIrq + idle;
- if (total == 0) total = 1;
+ int total = user + system + iowait + irq + softIrq + idle;
+ if (total == 0) total = 1;
- EventLog.writeEvent(EventLogTags.CPU,
- ((user+system+iowait+irq+softIrq) * 100) / total,
- (user * 100) / total,
- (system * 100) / total,
- (iowait * 100) / total,
- (irq * 100) / total,
- (softIrq * 100) / total);
+ EventLog.writeEvent(EventLogTags.CPU,
+ ((user+system+iowait+irq+softIrq) * 100) / total,
+ (user * 100) / total,
+ (system * 100) / total,
+ (iowait * 100) / total,
+ (irq * 100) / total,
+ (softIrq * 100) / total);
+ }
}
}
@@ -2282,8 +2291,10 @@
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
- if (mOnBattery) {
- int perc = bstats.startAddingCpuLocked();
+ final int perc = bstats.startAddingCpuLocked();
+ if (perc >= 0) {
+ int remainUTime = 0;
+ int remainSTime = 0;
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessCpuTracker.countStats();
@@ -2295,17 +2306,18 @@
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
- totalUTime += otherUTime;
- totalSTime += otherSTime;
+ remainUTime += otherUTime;
+ remainSTime += otherSTime;
+ totalUTime += st.rel_utime;
+ totalSTime += st.rel_stime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats;
if (ps == null || !ps.isActive()) {
pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
pr.info.uid, pr.processName);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2313,13 +2325,19 @@
st.batteryStats = ps = bstats.getProcessStatsLocked(
bstats.mapUid(st.uid), st.name);
}
- ps.addCpuTimeLocked(st.rel_utime-otherUTime,
- st.rel_stime-otherSTime);
- ps.addSpeedStepTimes(cpuSpeedTimes);
+ ps.addCpuTimeLocked(st.rel_utime - otherUTime,
+ st.rel_stime - otherSTime, cpuSpeedTimes);
}
}
- bstats.finishAddingCpuLocked(perc, totalUTime,
- totalSTime, cpuSpeedTimes);
+ final int userTime = mProcessCpuTracker.getLastUserTime();
+ final int systemTime = mProcessCpuTracker.getLastSystemTime();
+ final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime();
+ final int irqTime = mProcessCpuTracker.getLastIrqTime();
+ final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
+ final int idleTime = mProcessCpuTracker.getLastIdleTime();
+ bstats.finishAddingCpuLocked(perc, remainUTime,
+ remainSTime, totalUTime, totalSTime, userTime, systemTime,
+ iowaitTime, irqTime, softIrqTime, idleTime, cpuSpeedTimes);
}
}
}
@@ -7764,7 +7782,7 @@
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"getTaskThumbnail()");
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id, false);
if (tr != null) {
return tr.getTaskThumbnailLocked();
}
@@ -7877,7 +7895,7 @@
@Override
public void setTaskResizeable(int taskId, boolean resizeable) {
synchronized (this) {
- TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, false);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
return;
@@ -7891,6 +7909,25 @@
}
@Override
+ public void resizeTask(int taskId, Rect bounds) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "resizeTask()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId, true);
+ if (task == null) {
+ Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
+ return;
+ }
+ mStackSupervisor.resizeTaskLocked(task, bounds);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) {
if (!FileUtils.isValidExtFilename(filename)
|| !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) {
@@ -8025,7 +8062,7 @@
* @return Returns true if the given task was found and removed.
*/
private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId, false);
if (tr != null) {
tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, killProcess);
@@ -8199,14 +8236,13 @@
}
@Override
- public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
- throws RemoteException {
+ public int getActivityDisplayId(IBinder activityToken) throws RemoteException {
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
- if (stack != null) {
- return stack.mActivityContainer;
+ if (stack != null && stack.mActivityContainer.isAttachedLocked()) {
+ return stack.mActivityContainer.getDisplayId();
}
- return null;
+ return Display.DEFAULT_DISPLAY;
}
}
@@ -8279,7 +8315,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId);
+ TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(taskId, false);
return tr != null && tr.stack != null && tr.stack.isHomeStack();
}
} finally {
@@ -9980,8 +10016,9 @@
return true;
}
+ @Override
public Bundle getAssistContextExtras(int requestType) {
- PendingAssistExtras pae = enqueueAssistContext(requestType, null, null,
+ PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
UserHandle.getCallingUserId());
if (pae == null) {
return null;
@@ -9993,19 +10030,22 @@
} catch (InterruptedException e) {
}
}
- if (pae.result != null) {
- pae.extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
- }
}
synchronized (this) {
+ buildAssistBundleLocked(pae, pae.result);
mPendingAssistExtras.remove(pae);
mHandler.removeCallbacks(pae);
}
return pae.extras;
}
+ @Override
+ public void requestAssistContextExtras(int requestType, IResultReceiver receiver) {
+ enqueueAssistContext(requestType, null, null, receiver, UserHandle.getCallingUserId());
+ }
+
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
- int userHandle) {
+ IResultReceiver receiver, int userHandle) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"getAssistContextExtras()");
PendingAssistExtras pae;
@@ -10025,7 +10065,7 @@
Slog.w(TAG, "getAssistContextExtras failed: request process same as " + activity);
return null;
}
- pae = new PendingAssistExtras(activity, extras, intent, hint, userHandle);
+ pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, userHandle);
try {
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
requestType);
@@ -10039,13 +10079,33 @@
}
}
+ void pendingAssistExtrasTimedOutLocked(PendingAssistExtras pae) {
+ mPendingAssistExtras.remove(pae);
+ if (pae.receiver != null) {
+ // Caller wants result sent back to them.
+ try {
+ pae.receiver.send(0, null);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ private void buildAssistBundleLocked(PendingAssistExtras pae, Bundle result) {
+ if (result != null) {
+ pae.extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, result);
+ }
+ if (pae.hint != null) {
+ pae.extras.putBoolean(pae.hint, true);
+ }
+ }
+
public void reportAssistContextExtras(IBinder token, Bundle extras) {
PendingAssistExtras pae = (PendingAssistExtras)token;
synchronized (pae) {
pae.result = extras;
pae.haveResult = true;
pae.notifyAll();
- if (pae.intent == null) {
+ if (pae.intent == null && pae.receiver == null) {
// Caller is just waiting for the result.
return;
}
@@ -10053,17 +10113,23 @@
// We are now ready to launch the assist activity.
synchronized (this) {
+ buildAssistBundleLocked(pae, extras);
boolean exists = mPendingAssistExtras.remove(pae);
mHandler.removeCallbacks(pae);
if (!exists) {
// Timed out.
return;
}
+ if (pae.receiver != null) {
+ // Caller wants result sent back to them.
+ try {
+ pae.receiver.send(0, pae.extras);
+ } catch (RemoteException e) {
+ }
+ return;
+ }
}
- pae.intent.replaceExtras(extras);
- if (pae.hint != null) {
- pae.intent.putExtra(pae.hint, true);
- }
+ pae.intent.replaceExtras(pae.extras);
pae.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -10076,7 +10142,7 @@
}
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle) {
- return enqueueAssistContext(requestType, intent, hint, userHandle) != null;
+ return enqueueAssistContext(requestType, intent, hint, null, userHandle) != null;
}
public void registerProcessObserver(IProcessObserver observer) {
@@ -16275,10 +16341,11 @@
EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
- if (values.locale != null && !initLocale) {
- saveLocaleLocked(values.locale,
- !values.locale.equals(mConfiguration.locale),
- values.userSetLocale);
+ if (!initLocale && values.locale != null && values.userSetLocale) {
+ final String languageTag = values.locale.toLanguageTag();
+ SystemProperties.set("persist.sys.locale", languageTag);
+ mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG,
+ values.locale));
}
mConfigurationSeq++;
@@ -16385,36 +16452,6 @@
&& config.navigation == Configuration.NAVIGATION_NONAV);
}
- /**
- * Save the locale. You must be inside a synchronized (this) block.
- */
- private void saveLocaleLocked(Locale l, boolean isDiff, boolean isPersist) {
- final String languageTag = l.toLanguageTag();
- if (isDiff) {
- SystemProperties.set("user.locale", languageTag);
-
- // TODO: Who uses these ? There are no references to these system
- // properties in documents or code. Did the author intend to call
- // System.setProperty() instead ? Even that wouldn't have any effect.
- SystemProperties.set("user.language", l.getLanguage());
- SystemProperties.set("user.region", l.getCountry());
- }
-
- if (isPersist) {
- SystemProperties.set("persist.sys.locale", languageTag);
-
- // These values are *deprecated*, use persist.sys.locale instead.
- //
- // TODO: Stop setting these values once all code that references
- // them has been removed.
- SystemProperties.set("persist.sys.language", l.getLanguage());
- SystemProperties.set("persist.sys.country", l.getCountry());
- SystemProperties.set("persist.sys.localevar", l.getVariant());
-
- mHandler.sendMessage(mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG, l));
- }
- }
-
@Override
public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
synchronized (this) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index b3f47e9..0cbc9d7 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -479,10 +479,16 @@
AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
realTheme, com.android.internal.R.styleable.Window, userId);
+ final boolean translucent = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false)
+ || (!ent.array.hasValue(
+ com.android.internal.R.styleable.Window_windowIsTranslucent)
+ && ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowSwipeToDismiss,
+ false));
fullscreen = ent != null && !ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowIsFloating, false)
- && !ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+ && !translucent;
noDisplay = ent != null && ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
@@ -712,6 +718,17 @@
pendingOptions.getCustomExitResId(),
pendingOptions.getOnAnimationStartListener());
break;
+ case ActivityOptions.ANIM_CLIP_REVEAL:
+ service.mWindowManager.overridePendingAppTransitionClipReveal(
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight());
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX()+pendingOptions.getWidth(),
+ pendingOptions.getStartY()+pendingOptions.getHeight()));
+ }
+ break;
case ActivityOptions.ANIM_SCALE_UP:
service.mWindowManager.overridePendingAppTransitionScaleUp(
pendingOptions.getStartX(), pendingOptions.getStartY(),
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4d7305d..c3343f5 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -152,25 +152,25 @@
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
- private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
+ private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
/**
* Used for validating app tokens with window manager.
*/
- final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
+ final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<>();
/**
* List of running activities, sorted by recent usage.
* The first entry in the list is the least recently used.
* It contains HistoryRecord objects.
*/
- final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
+ final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
/**
* Animations that for the current transition have requested not to
* be considered for the transition animation.
*/
- final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
+ final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();
/**
* When we are in the process of pausing an activity, before starting the
@@ -346,6 +346,10 @@
return count;
}
+ int numTasks() {
+ return mTaskHistory.size();
+ }
+
ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
RecentTasks recentTasks) {
mActivityContainer = activityContainer;
@@ -1154,6 +1158,23 @@
return null;
}
+ private ActivityStack getNextVisibleStackLocked() {
+ ArrayList<ActivityStack> stacks = mStacks;
+ final ActivityRecord parent = mActivityContainer.mParentActivity;
+ if (parent != null) {
+ stacks = parent.task.stack.mStacks;
+ }
+ if (stacks != null) {
+ for (int i = stacks.size() - 1; i >= 0; --i) {
+ ActivityStack stack = stacks.get(i);
+ if (stack != this && stack.isStackVisibleLocked()) {
+ return stack;
+ }
+ }
+ }
+ return null;
+ }
+
// Checks if any of the stacks above this one has a fullscreen activity behind it.
// If so, this stack is hidden, otherwise it is visible.
private boolean isStackVisibleLocked() {
@@ -1482,7 +1503,7 @@
return result;
}
- final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
+ private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (!mService.mBooting && !mService.mBooted) {
@@ -1510,8 +1531,17 @@
final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
- // There are no more activities! Let's just start up the
- // Launcher...
+ // There are no more activities!
+ final String reason = "noMoreActivities";
+ if (!mFullscreen) {
+ // Try to move focus to the next visible stack with a running activity if this
+ // stack is not covering the entire screen.
+ final ActivityStack stack = getNextVisibleStackLocked();
+ if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
+ return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
+ }
+ }
+ // Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -1519,7 +1549,7 @@
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
- mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
+ mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
next.delayedResume = false;
@@ -2516,20 +2546,45 @@
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
ActivityRecord next = topRunningActivityLocked(null);
+ final String myReason = reason + " adjustFocus";
if (next != r) {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(),
- reason + " adjustFocus");
+ // For non-fullscreen stack, we want to move the focus to the next visible
+ // stack to prevent the home screen from moving to the top and obscuring
+ // other visible stacks.
+ if (!mFullscreen
+ && adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ return;
+ }
+ // Move the home stack to the top if this stack is fullscreen or there is no
+ // other visible stack.
+ mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), myReason);
}
}
- ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+
+ final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
if (top != null) {
- mService.setFocusedActivityLocked(top, reason + " adjustTopFocus");
+ mService.setFocusedActivityLocked(top, myReason);
}
}
}
+ private boolean adjustFocusToNextVisibleStackLocked(ActivityStack inStack, String reason) {
+ final ActivityStack stack = (inStack != null) ? inStack : getNextVisibleStackLocked();
+ final String myReason = reason + " adjustFocusToNextVisibleStack";
+ if (stack == null) {
+ return false;
+ }
+ final ActivityRecord top = stack.topRunningActivityLocked(null);
+ if (top == null) {
+ return false;
+ }
+ stack.moveToFront(myReason);
+ mService.setFocusedActivityLocked(top, myReason);
+ return true;
+ }
+
final void stopActivityLocked(ActivityRecord r) {
if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
@@ -2999,6 +3054,8 @@
* representation) and cleaning things up as a result of its hosting
* processing going away, in which case there is no remaining client-side
* state to destroy so only the cleanup here is needed.
+ *
+ * Note: Call before #removeActivityFromHistoryLocked.
*/
final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
boolean setState) {
@@ -3410,7 +3467,7 @@
if (DEBUG_CLEANUP) Slog.v(
TAG, "Record #" + i + " " + r + ": app=" + r.app);
if (r.app == app) {
- boolean remove;
+ final boolean remove;
if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
// Don't currently have state for the activity, or
// it is finishing -- always remove it.
@@ -3444,8 +3501,6 @@
mService.updateUsageStats(r, false);
}
}
- removeActivityFromHistoryLocked(r, "appDied");
-
} else {
// We have the current state for this activity, so
// it can be restarted later when needed.
@@ -3464,8 +3519,10 @@
r.icicle = null;
}
}
-
cleanUpActivityLocked(r, true, true);
+ if (remove) {
+ removeActivityFromHistoryLocked(r, "appDied");
+ }
}
}
}
@@ -4126,8 +4183,14 @@
}
void removeTask(TaskRecord task, String reason) {
+ removeTask(task, reason, true);
+ }
+
+ void removeTask(TaskRecord task, String reason, boolean removeFromWindowManager) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
- mWindowManager.removeTask(task.taskId);
+ if (removeFromWindowManager) {
+ mWindowManager.removeTask(task.taskId);
+ }
final ActivityRecord r = mResumedActivity;
if (r != null && r.task == task) {
mResumedActivity = null;
@@ -4161,16 +4224,24 @@
}
if (mTaskHistory.isEmpty()) {
- if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
+ if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack=" + this);
+ final boolean notHomeStack = !isHomeStack();
if (isOnHomeDisplay()) {
- mStackSupervisor.moveHomeStack(!isHomeStack(), reason + " leftTaskHistoryEmpty");
+ String myReason = reason + " leftTaskHistoryEmpty";
+ if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ mStackSupervisor.moveHomeStack(notHomeStack, myReason);
+ }
}
if (mStacks != null) {
mStacks.remove(this);
mStacks.add(0, this);
}
- mActivityContainer.onTaskListEmptyLocked();
+ if (notHomeStack) {
+ mActivityContainer.onTaskListEmptyLocked();
+ }
}
+
+ task.stack = null;
}
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1aa2a10..907381e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -386,8 +386,8 @@
return mLastFocusedStack;
}
- // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
- // top of all visible stacks.
+ /** Top of all visible stacks. Use {@link ActivityStack#isStackVisibleLocked} to determine if a
+ * specific stack is visible or not. */
boolean isFrontStack(ActivityStack stack) {
final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
if (parent != null) {
@@ -462,6 +462,16 @@
}
TaskRecord anyTaskForIdLocked(int id) {
+ return anyTaskForIdLocked(id, true);
+ }
+
+ /**
+ * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+ * @param id Id of the task we would like returned.
+ * @param restoreFromRecents If the id was not in the active list, but was found in recents,
+ * restore the task from recents to the active list.
+ */
+ TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -482,6 +492,10 @@
return null;
}
+ if (!restoreFromRecents) {
+ return task;
+ }
+
if (!restoreRecentTaskLocked(task)) {
if (DEBUG_RECENTS) Slog.w(TAG, "Couldn't restore task id=" + id + " found in recents");
return null;
@@ -516,12 +530,12 @@
if (mCurTaskId <= 0) {
mCurTaskId = 1;
}
- } while (anyTaskForIdLocked(mCurTaskId) != null);
+ } while (anyTaskForIdLocked(mCurTaskId, false) != null);
return mCurTaskId;
}
ActivityRecord resumedAppLocked() {
- ActivityStack stack = getFocusedStack();
+ ActivityStack stack = mFocusedStack;
if (stack == null) {
return null;
}
@@ -725,7 +739,7 @@
}
ActivityRecord topRunningActivityLocked() {
- final ActivityStack focusedStack = getFocusedStack();
+ final ActivityStack focusedStack = mFocusedStack;
ActivityRecord r = focusedStack.topRunningActivityLocked(null);
if (r != null) {
return r;
@@ -871,7 +885,7 @@
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
- stack = getFocusedStack();
+ stack = mFocusedStack;
} else {
stack = container.mStack;
}
@@ -1488,7 +1502,7 @@
outActivity[0] = r;
}
- final ActivityStack stack = getFocusedStack();
+ final ActivityStack stack = mFocusedStack;
if (voiceSession == null && (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
@@ -1692,7 +1706,7 @@
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
+ checkedCaller = mFocusedStack.topRunningNonDelayedActivityLocked(notTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
// Caller is not the same as launcher, so always needed.
@@ -2016,7 +2030,7 @@
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- ActivityStack topStack = getFocusedStack();
+ ActivityStack topStack = mFocusedStack;
ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
@@ -2468,13 +2482,14 @@
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
- targetStack = getFocusedStack();
+ targetStack = mFocusedStack;
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}
+
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) {
@@ -2626,6 +2641,48 @@
}
}
+ /** Makes sure the input task is in a stack with the specified bounds by either resizing the
+ * current task stack if it only has one entry, moving the task to a stack that matches the
+ * bounds, or creating a new stack with the required bounds. Also, makes the task resizeable.*/
+ void resizeTaskLocked(TaskRecord task, Rect bounds) {
+ task.mResizeable = true;
+ final ActivityStack currentStack = task.stack;
+ if (currentStack.isHomeStack()) {
+ // Can't move task off the home stack. Sorry!
+ return;
+ }
+
+ final int matchingStackId = mWindowManager.getStackIdWithBounds(bounds);
+ if (matchingStackId != -1) {
+ // There is already a stack with the right bounds!
+ if (currentStack != null && currentStack.mStackId == matchingStackId) {
+ // Nothing to do here. Already in the right stack...
+ return;
+ }
+ // Move task to stack with matching bounds.
+ moveTaskToStackLocked(task.taskId, matchingStackId, true);
+ return;
+ }
+
+ if (currentStack != null && currentStack.numTasks() == 1) {
+ // Just resize the current stack since this is the task in it.
+ resizeStackLocked(currentStack.mStackId, bounds);
+ return;
+ }
+
+ // Create new stack and move the task to it.
+ final int displayId = (currentStack != null && currentStack.mDisplayId != -1)
+ ? currentStack.mDisplayId : Display.DEFAULT_DISPLAY;
+ ActivityStack newStack = createStackOnDisplay(getNextStackId(), displayId);
+
+ if (newStack == null) {
+ Slog.e(TAG, "resizeTaskLocked: Can't create stack for task=" + task);
+ return;
+ }
+ moveTaskToStackLocked(task.taskId, newStack.mStackId, true);
+ resizeStackLocked(newStack.mStackId, bounds);
+ }
+
ActivityStack createStackOnDisplay(int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -2661,7 +2718,7 @@
final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack tmpStack = homeDisplayStacks.get(stackNdx);
- if (!tmpStack.isHomeStack()) {
+ if (!tmpStack.isHomeStack() && tmpStack.mFullscreen) {
stack = tmpStack;
break;
}
@@ -2704,6 +2761,7 @@
void moveTaskToStackLocked(int taskId, int stackId, boolean toTop) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task == null) {
+ Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
return;
}
final ActivityStack stack = getStack(stackId);
@@ -2711,9 +2769,11 @@
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- task.stack.removeTask(task, "moveTaskToStack");
+ mWindowManager.moveTaskToStack(taskId, stackId, toTop);
+ if (task.stack != null) {
+ task.stack.removeTask(task, "moveTaskToStack", false);
+ }
stack.addTask(task, toTop, true);
- mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
}
@@ -3054,7 +3114,7 @@
}
boolean switchUserLocked(int userId, UserStartedState uss) {
- mUserStackInFront.put(mCurrentUser, getFocusedStack().getStackId());
+ mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId());
final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
mCurrentUser = userId;
@@ -3178,7 +3238,7 @@
}
ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
- return getFocusedStack().getDumpActivitiesLocked(name);
+ return mFocusedStack.getDumpActivitiesLocked(name);
}
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
@@ -3928,6 +3988,10 @@
}
void onTaskListEmptyLocked() {
+ mHandler.removeMessages(CONTAINER_TASK_LIST_EMPTY_TIMEOUT, this);
+ detachLocked();
+ deleteActivityContainer(this);
+ mHandler.obtainMessage(CONTAINER_CALLBACK_TASK_LIST_EMPTY, this).sendToTarget();
}
@Override
@@ -4016,13 +4080,6 @@
return false;
}
- void onTaskListEmptyLocked() {
- mHandler.removeMessages(CONTAINER_TASK_LIST_EMPTY_TIMEOUT, this);
- detachLocked();
- deleteActivityContainer(this);
- mHandler.obtainMessage(CONTAINER_CALLBACK_TASK_LIST_EMPTY, this).sendToTarget();
- }
-
private void setSurfaceIfReadyLocked() {
if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReadyLocked: mDrawn=" + mDrawn +
" mContainerState=" + mContainerState + " mSurface=" + mSurface);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 7ab3794..6a29d85 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -187,10 +187,12 @@
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
+ r.enqueueClockTime = System.currentTimeMillis();
}
public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
mOrderedBroadcasts.add(r);
+ r.enqueueClockTime = System.currentTimeMillis();
}
public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index b2cfd7a..9a4d7a0 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -52,6 +52,7 @@
final int appOp; // an app op that is associated with this broadcast
final List receivers; // contains BroadcastFilter and ResolveInfo
IIntentReceiver resultTo; // who receives final result if non-null
+ long enqueueClockTime; // the clock time the broadcast was enqueued
long dispatchTime; // when dispatch started on this set of receivers
long dispatchClockTime; // the clock time the dispatch started
long receiverTime; // when current receiver started for timeouts.
@@ -102,7 +103,9 @@
pw.print(prefix); pw.print("requiredPermission="); pw.print(requiredPermission);
pw.print(" appOp="); pw.println(appOp);
}
- pw.print(prefix); pw.print("dispatchClockTime=");
+ pw.print(prefix); pw.print("enqueueClockTime=");
+ pw.print(new Date(enqueueClockTime));
+ pw.print(" dispatchClockTime=");
pw.println(new Date(dispatchClockTime));
pw.print(prefix); pw.print("dispatchTime=");
TimeUtils.formatDuration(dispatchTime, now, pw);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index eaece09..473f5db 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -182,6 +182,7 @@
/** The controller for the volume UI. */
private final VolumeController mVolumeController = new VolumeController();
+ private final ControllerService mControllerService = new ControllerService();
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
@@ -369,7 +370,8 @@
// Streams currently muted by ringer mode
private int mRingerModeMutedStreams;
- /** @see System#MUTE_STREAMS_AFFECTED */
+ /** Streams that can be muted. Do not resolve to aliases when checking.
+ * @see System#MUTE_STREAMS_AFFECTED */
private int mMuteAffectedStreams;
/**
@@ -579,8 +581,7 @@
AudioSystem.setErrorCallback(mAudioSystemCallback);
- boolean cameraSoundForced = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_camera_sound_forced);
+ boolean cameraSoundForced = readCameraSoundForced();
mCameraSoundForced = new Boolean(cameraSoundForced);
sendMsg(mAudioHandler,
MSG_SET_FORCE_USE,
@@ -708,6 +709,7 @@
SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
StreamOverride.init(mContext);
+ mControllerService.init();
}
private void createAudioSystemThread() {
@@ -996,15 +998,15 @@
boolean isMuteAdjust = isMuteAdjust(direction);
+ if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
+ return;
+ }
+
// use stream type alias here so that streams with same alias have the same behavior,
// including with regard to silent mode control (e.g the use of STREAM_RING below and in
// checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
int streamTypeAlias = mStreamVolumeAlias[streamType];
- if (isMuteAdjust && !isStreamAffectedByMute(streamTypeAlias)) {
- return;
- }
-
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
final int device = getDeviceForStream(streamTypeAlias);
@@ -1104,11 +1106,6 @@
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (streamTypeAlias == mStreamVolumeAlias[stream]) {
mStreamStates[stream].mute(state);
-
- Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream);
- intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
- sendBroadcastToAll(intent);
}
}
} else if ((direction == AudioManager.ADJUST_RAISE) &&
@@ -1185,8 +1182,7 @@
synchronized (mHdmiTvClient) {
final long token = Binder.clearCallingIdentity();
try {
- mHdmiTvClient.setSystemAudioVolume(
- (oldVolume + 5) / 10, (newVolume + 5) / 10, maxVolume);
+ mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1429,6 +1425,7 @@
private void sendBroadcastToAll(Intent intent) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
@@ -1438,6 +1435,7 @@
}
private void sendStickyBroadcastToAll(Intent intent) {
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
final long ident = Binder.clearCallingIdentity();
try {
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
@@ -1456,16 +1454,6 @@
flags = updateFlagsForSystemAudio(flags);
}
mVolumeController.postVolumeChanged(streamType, flags);
-
- if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) {
- oldIndex = (oldIndex + 5) / 10;
- index = (index + 5) / 10;
- Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
- intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
- intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
- sendBroadcastToAll(intent);
- }
}
// If Hdmi-CEC system audio mode is on, we show volume bar only when TV
@@ -1833,7 +1821,7 @@
}
public void setRingerModeInternal(int ringerMode, String caller) {
- enforceSelfOrSystemUI("setRingerModeInternal");
+ enforceVolumeController("setRingerModeInternal");
setRingerMode(ringerMode, caller, false /*external*/);
}
@@ -1920,6 +1908,15 @@
entry.setValue(10);
}
}
+ // Persist volume for stream ring when it is changed here
+ final int device = getDeviceForStream(streamType);
+ sendMsg(mAudioHandler,
+ MSG_PERSIST_VOLUME,
+ SENDMSG_QUEUE,
+ device,
+ 0,
+ mStreamStates[streamType],
+ PERSIST_DELAY);
}
}
mStreamStates[streamType].mute(false);
@@ -3206,6 +3203,7 @@
return false;
}
+ @Override
public boolean isStreamAffectedByMute(int streamType) {
return (mMuteAffectedStreams & (1 << streamType)) != 0;
}
@@ -3493,6 +3491,7 @@
private int mIndexMax;
private final ConcurrentHashMap<Integer, Integer> mIndex =
new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
+ private final Intent mVolumeChanged;
private VolumeStreamState(String settingName, int streamType) {
@@ -3504,6 +3503,8 @@
mIndexMax *= 10;
readSettings();
+ mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
}
public String getSettingNameForDevice(int device) {
@@ -3618,8 +3619,10 @@
}
public boolean setIndex(int index, int device) {
+ boolean changed = false;
+ int oldIndex;
synchronized (VolumeStreamState.class) {
- int oldIndex = getIndex(device);
+ oldIndex = getIndex(device);
index = getValidIndex(index);
synchronized (mCameraSoundForced) {
if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
@@ -3628,7 +3631,8 @@
}
mIndex.put(device, index);
- if (oldIndex != index) {
+ changed = oldIndex != index;
+ if (changed) {
// Apply change to all streams using this one as alias
// if changing volume of current device, also change volume of current
// device on aliased stream
@@ -3646,11 +3650,16 @@
}
}
}
- return true;
- } else {
- return false;
}
}
+ if (changed) {
+ oldIndex = (oldIndex + 5) / 10;
+ index = (index + 5) / 10;
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
+ sendBroadcastToAll(mVolumeChanged);
+ }
+ return changed;
}
public int getIndex(int device) {
@@ -3707,9 +3716,12 @@
}
public void mute(boolean state) {
+ boolean changed = false;
synchronized (VolumeStreamState.class) {
if (state != mIsMuted) {
+ changed = true;
mIsMuted = state;
+
// Set the new mute volume. This propagates the values to
// the audio system, otherwise the volume won't be changed
// at the lower level.
@@ -3721,6 +3733,13 @@
this, 0);
}
}
+ if (changed) {
+ // Stream mute changed, fire the intent.
+ Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
+ sendBroadcastToAll(intent);
+ }
}
public int getStreamType() {
@@ -5013,7 +5032,7 @@
@Override
public void setRemoteStreamVolume(int index) {
- enforceSelfOrSystemUI("set the remote stream volume");
+ enforceVolumeController("set the remote stream volume");
mMediaFocusControl.setRemoteStreamVolume(index);
}
@@ -5058,6 +5077,12 @@
return mMediaFocusControl.getCurrentAudioFocus();
}
+ private boolean readCameraSoundForced() {
+ return SystemProperties.getBoolean("audio.camerasound.force", false) ||
+ mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_camera_sound_forced);
+ }
+
//==========================================================================================
// Device orientation
//==========================================================================================
@@ -5088,8 +5113,7 @@
null,
0);
- boolean cameraSoundForced = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_camera_sound_forced);
+ boolean cameraSoundForced = readCameraSoundForced();
synchronized (mSettingsLock) {
boolean cameraSoundForcedChanged = false;
synchronized (mCameraSoundForced) {
@@ -5333,7 +5357,7 @@
@Override
public void disableSafeMediaVolume() {
- enforceSelfOrSystemUI("disable the safe media volume");
+ enforceVolumeController("disable the safe media volume");
synchronized (mSafeMediaVolumeState) {
setSafeMediaVolumeEnabled(false);
if (mPendingVolumeCommand != null) {
@@ -5504,7 +5528,9 @@
pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
pw.print(" mMcc="); pw.println(mMcc);
+ pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
pw.print(" mHasVibrator="); pw.println(mHasVibrator);
+ pw.print(" mControllerService="); pw.println(mControllerService);
dumpAudioPolicies(pw);
}
@@ -5528,14 +5554,17 @@
}
}
- private void enforceSelfOrSystemUI(String action) {
+ private void enforceVolumeController(String action) {
+ if (mControllerService.mUid != 0 && Binder.getCallingUid() == mControllerService.mUid) {
+ return;
+ }
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
"Only SystemUI can " + action);
}
@Override
public void setVolumeController(final IVolumeController controller) {
- enforceSelfOrSystemUI("set the volume controller");
+ enforceVolumeController("set the volume controller");
// return early if things are not actually changing
if (mVolumeController.isSameBinder(controller)) {
@@ -5566,7 +5595,7 @@
@Override
public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
- enforceSelfOrSystemUI("notify about volume controller visibility");
+ enforceVolumeController("notify about volume controller visibility");
// return early if the controller is not current
if (!mVolumeController.isSameBinder(controller)) {
@@ -5751,6 +5780,11 @@
public void setRingerModeInternal(int ringerMode, String caller) {
AudioService.this.setRingerModeInternal(ringerMode, caller);
}
+
+ @Override
+ public int getVolumeControllerUid() {
+ return mControllerService.mUid;
+ }
}
//==========================================================================================
@@ -5915,4 +5949,42 @@
private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
new HashMap<IBinder, AudioPolicyProxy>();
private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
+
+ private class ControllerService extends ContentObserver {
+ private int mUid;
+ private ComponentName mComponent;
+
+ public ControllerService() {
+ super(null);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{mUid=%d,mComponent=%s}", mUid, mComponent);
+ }
+
+ public void init() {
+ onChange(true);
+ mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT), false, this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mUid = 0;
+ mComponent = null;
+ final String setting = Settings.Secure.getString(mContentResolver,
+ Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT);
+ if (setting == null) return;
+ try {
+ mComponent = ComponentName.unflattenFromString(setting);
+ if (mComponent == null) return;
+ mUid = mContext.getPackageManager()
+ .getApplicationInfo(mComponent.getPackageName(), 0).uid;
+ } catch (Exception e) {
+ Log.w(TAG, "Error loading controller service", e);
+ }
+ if (DEBUG_VOL) Log.d(TAG, "Reloaded controller service: " + this);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index d919bf6..93d37f1 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -52,20 +52,9 @@
// auto-brightness adjustment setting.
private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
- // Light sensor event rate in milliseconds.
- private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
-
// Period of time in which to consider light samples in milliseconds.
private static final int AMBIENT_LIGHT_HORIZON = 10000;
- // Stability requirements in milliseconds for accepting a new brightness level. This is used
- // for debouncing the light sensor. Different constants are used to debounce the light sensor
- // when adapting to brighter or darker environments. This parameter controls how quickly
- // brightness changes occur in response to an observed change in light level that exceeds the
- // hysteresis threshold.
- private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
- private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
-
// Hysteresis constraints for brightening or darkening.
// The recent lux must have changed by at least this fraction relative to the
// current ambient lux before a change will be considered.
@@ -121,6 +110,22 @@
private final int mScreenBrightnessRangeMaximum;
private final float mDozeScaleFactor;
+ // Light sensor event rate in milliseconds.
+ private final int mLightSensorRate;
+
+ // Stability requirements in milliseconds for accepting a new brightness level. This is used
+ // for debouncing the light sensor. Different constants are used to debounce the light sensor
+ // when adapting to brighter or darker environments. This parameter controls how quickly
+ // brightness changes occur in response to an observed change in light level that exceeds the
+ // hysteresis threshold.
+ private final long mBrighteningLightDebounceConfig;
+ private final long mDarkeningLightDebounceConfig;
+
+ // If true immediately after the screen is turned on the controller will try to adjust the
+ // brightness based on the current sensor reads. If false, the controller will collect more data
+ // and only then decide whether to change brightness.
+ private final boolean mResetAmbientLuxAfterWarmUpConfig;
+
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
// May be 0 if no warm-up is required.
@@ -176,7 +181,9 @@
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
- int brightnessMin, int brightnessMax, float dozeScaleFactor) {
+ int brightnessMin, int brightnessMax, float dozeScaleFactor,
+ int lightSensorRate, long brighteningLightDebounceConfig,
+ long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig) {
mCallbacks = callbacks;
mTwilight = LocalServices.getService(TwilightManager.class);
mSensorManager = sensorManager;
@@ -185,9 +192,13 @@
mScreenBrightnessRangeMaximum = brightnessMax;
mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;
mDozeScaleFactor = dozeScaleFactor;
+ mLightSensorRate = lightSensorRate;
+ mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
+ mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
+ mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mHandler = new AutomaticBrightnessHandler(looper);
- mAmbientLightRingBuffer = new AmbientLightRingBuffer();
+ mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate);
if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
@@ -226,6 +237,9 @@
pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
+ pw.println(" mBrighteningLightDebounceConfig=" + mBrighteningLightDebounceConfig);
+ pw.println(" mDarkeningLightDebounceConfig=" + mDarkeningLightDebounceConfig);
+ pw.println(" mResetAmbientLuxAfterWarmUpConfig=" + mResetAmbientLuxAfterWarmUpConfig);
pw.println();
pw.println("Automatic Brightness Controller State:");
@@ -252,13 +266,13 @@
mLightSensorEnabled = true;
mLightSensorEnableTime = SystemClock.uptimeMillis();
mSensorManager.registerListener(mLightSensorListener, mLightSensor,
- LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
+ mLightSensorRate * 1000, mHandler);
return true;
}
} else {
if (mLightSensorEnabled) {
mLightSensorEnabled = false;
- mAmbientLuxValid = false;
+ mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
mRecentLightSamples = 0;
mAmbientLightRingBuffer.clear();
mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
@@ -347,7 +361,7 @@
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
}
- return earliestValidTime + BRIGHTENING_LIGHT_DEBOUNCE;
+ return earliestValidTime + mBrighteningLightDebounceConfig;
}
private long nextAmbientLightDarkeningTransition(long time) {
@@ -359,7 +373,7 @@
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
}
- return earliestValidTime + DARKENING_LIGHT_DEBOUNCE;
+ return earliestValidTime + mDarkeningLightDebounceConfig;
}
private void updateAmbientLux() {
@@ -420,7 +434,7 @@
// should be enough time to decide whether we should actually transition to the new
// weighted ambient lux or not.
nextTransitionTime =
- nextTransitionTime > time ? nextTransitionTime : time + LIGHT_SENSOR_RATE_MILLIS;
+ nextTransitionTime > time ? nextTransitionTime : time + mLightSensorRate;
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for "
+ nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
@@ -559,8 +573,6 @@
// Proportional extra capacity of the buffer beyond the expected number of light samples
// in the horizon
private static final float BUFFER_SLACK = 1.5f;
- private static final int DEFAULT_CAPACITY =
- (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / LIGHT_SENSOR_RATE_MILLIS);
private float[] mRingLux;
private long[] mRingTime;
private int mCapacity;
@@ -571,8 +583,8 @@
private int mEnd;
private int mCount;
- public AmbientLightRingBuffer() {
- this(DEFAULT_CAPACITY);
+ public AmbientLightRingBuffer(long lightSensorRate) {
+ this((int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate));
}
public AmbientLightRingBuffer(int initialCapacity) {
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 6e61e41..4e075c3 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -37,7 +37,6 @@
import android.opengl.EGLSurface;
import android.opengl.GLES20;
import android.opengl.GLES11Ext;
-import android.util.FloatMath;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.Surface.OutOfResourcesException;
@@ -372,13 +371,13 @@
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Draw the frame.
- float one_minus_level = 1 - level;
- float cos = FloatMath.cos((float)Math.PI * one_minus_level);
- float sign = cos < 0 ? -1 : 1;
- float opacity = -FloatMath.pow(one_minus_level, 2) + 1;
- float saturation = FloatMath.pow(level, 4);
- float scale = (-FloatMath.pow(one_minus_level, 2) + 1) * 0.1f + 0.9f;
- float gamma = (0.5f * sign * FloatMath.pow(cos, 2) + 0.5f) * 0.9f + 0.1f;
+ double one_minus_level = 1 - level;
+ double cos = Math.cos(Math.PI * one_minus_level);
+ double sign = cos < 0 ? -1 : 1;
+ float opacity = (float) -Math.pow(one_minus_level, 2) + 1;
+ float saturation = (float) Math.pow(level, 4);
+ float scale = (float) ((-Math.pow(one_minus_level, 2) + 1) * 0.1d + 0.9d);
+ float gamma = (float) ((0.5d * sign * Math.pow(cos, 2) + 0.5d) * 0.9d + 0.1d);
drawFaded(opacity, 1.f / gamma, saturation, scale);
if (checkGlErrors("drawFrame")) {
return false;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 78610ff..cf1f4b0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -302,6 +302,15 @@
mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
+ int lightSensorRate = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
+ long brighteningLightDebounce = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
+ long darkeningLightDebounce = resources.getInteger(
+ com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
+ boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
+ com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
+
if (mUseSoftwareAutoBrightnessConfig) {
int[] lux = resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels);
@@ -336,7 +345,9 @@
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), sensorManager, screenAutoBrightnessSpline,
lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
- mScreenBrightnessRangeMaximum, dozeScaleFactor);
+ mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
+ brighteningLightDebounce, darkeningLightDebounce,
+ autoBrightnessResetAmbientLuxAfterWarmUp);
}
}
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 5b6f35b..af9f456 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -355,7 +355,7 @@
if (mWindow != null) {
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
- DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, 200);
+ DumpUtils.dumpAsync(mUiHandler, mWindow, ipw, "", 200);
}
}
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index 9ca5fda..3f4eab9 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -153,7 +153,7 @@
}
@Override
- public void dump(PrintWriter pw) {
+ public void dump(PrintWriter pw, String prefix) {
pw.println("mWindowVisible=" + mWindowVisible);
pw.println("mWindowX=" + mWindowX);
pw.println("mWindowY=" + mWindowY);
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index c939861..f163555 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -123,7 +123,7 @@
pw.println("mDisplayController:");
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
ipw.increaseIndent();
- DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
+ DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, "", 200);
}
}
diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java
index dbb59b2..31c1eea 100644
--- a/services/core/java/com/android/server/display/WifiDisplayController.java
+++ b/services/core/java/com/android/server/display/WifiDisplayController.java
@@ -209,7 +209,7 @@
}
@Override
- public void dump(PrintWriter pw) {
+ public void dump(PrintWriter pw, String prefix) {
pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting);
pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled);
pw.println("mWfdEnabled=" + mWfdEnabled);
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 4521c28..458928f 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -137,10 +137,10 @@
DumpUtils.dumpAsync(mHandler, new DumpUtils.Dump() {
@Override
- public void dump(PrintWriter pw) {
+ public void dump(PrintWriter pw, String prefix) {
mController.dump(pw);
}
- }, pw, 200);
+ }, pw, "", 200);
}
private boolean isDreamingInternal() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 4f458e6..cfc9132 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -881,7 +881,7 @@
HdmiLogger.debug("Set Arc Status[old:%b new:%b]", mArcEstablished, enabled);
boolean oldStatus = mArcEstablished;
// 1. Enable/disable ARC circuit.
- mService.setAudioReturnChannel(getAvrDeviceInfo().getPortId(), enabled);
+ setAudioReturnChannel(enabled);
// 2. Notify arc status to audio service.
notifyArcStatusToAudioService(enabled);
// 3. Update arc status;
@@ -889,6 +889,18 @@
return oldStatus;
}
+ /**
+ * Switch hardware ARC circuit in the system.
+ */
+ @ServiceThreadOnly
+ void setAudioReturnChannel(boolean enabled) {
+ assertRunOnServiceThread();
+ HdmiDeviceInfo avr = getAvrDeviceInfo();
+ if (avr != null) {
+ mService.setAudioReturnChannel(avr.getPortId(), enabled);
+ }
+ }
+
@ServiceThreadOnly
private void updateArcFeatureStatus(int portId, boolean isConnected) {
assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 1bbd038..f7555e9 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -262,6 +262,7 @@
// Turn off system audio mode and update settings.
tv().setSystemAudioMode(false, true);
if (tv().isArcEstabilished()) {
+ tv().setAudioReturnChannel(false);
addAndStartAction(new RequestArcTerminationAction(localDevice(), address));
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1a0f81d..a5efc83 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.media.AudioManager;
+import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.IRemoteVolumeController;
@@ -59,6 +60,7 @@
import android.util.SparseArray;
import android.view.KeyEvent;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
@@ -94,6 +96,7 @@
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
private AudioManager mAudioManager;
+ private AudioManagerInternal mAudioManagerInternal;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
@@ -121,6 +124,7 @@
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe();
@@ -334,6 +338,7 @@
*/
private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
int resolvedUserId) {
+ if (isCurrentVolumeController(uid)) return;
if (getContext()
.checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
!= PackageManager.PERMISSION_GRANTED
@@ -343,7 +348,18 @@
}
}
- private void enforceStatusBarPermission(String action, int pid, int uid) {
+ private boolean isCurrentVolumeController(int uid) {
+ if (mAudioManagerInternal != null) {
+ final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
+ if (vcuid > 0 && uid == vcuid) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void enforceSystemUiPermission(String action, int pid, int uid) {
+ if (isCurrentVolumeController(uid)) return;
if (getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
pid, uid) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Only system ui may " + action);
@@ -789,7 +805,7 @@
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- enforceStatusBarPermission("listen for volume changes", pid, uid);
+ enforceSystemUiPermission("listen for volume changes", pid, uid);
mRvc = rvc;
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 02cacd9..9b6b5fb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -50,6 +50,7 @@
import android.database.ContentObserver;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.AudioManagerInternal;
import android.media.AudioSystem;
import android.media.IRingtonePlayer;
import android.net.Uri;
@@ -179,6 +180,7 @@
private IActivityManager mAm;
AudioManager mAudioManager;
+ AudioManagerInternal mAudioManagerInternal;
StatusBarManagerInternal mStatusBar;
Vibrator mVibrator;
@@ -207,7 +209,7 @@
private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
private ComponentName mEffectsSuppressor;
private int mListenerHints; // right now, all hints are global
- private int mInterruptionFilter; // current ZEN mode as communicated to listeners
+ private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
// for enabling and disabling notification pulse behavior
private boolean mScreenOn = true;
@@ -931,6 +933,7 @@
mDisableNotificationEffects = true;
}
mZenModeHelper.readZenModeFromSetting();
+ mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
mUserProfiles.updateCache(getContext());
listenForCallState();
@@ -996,6 +999,7 @@
// Grab our optional AudioService
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
mZenModeHelper.onSystemReady();
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
// This observer will force an update when observe is called, causing us to
@@ -1468,7 +1472,7 @@
@Override
public ZenModeConfig getZenModeConfig() {
- enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
+ enforceSystemOrSystemUIOrVolume("INotificationManager.getZenModeConfig");
return mZenModeHelper.getConfig();
}
@@ -1479,6 +1483,17 @@
}
@Override
+ public void setZenMode(int mode) throws RemoteException {
+ enforceSystemOrSystemUIOrVolume("INotificationManager.setZenMode");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mZenModeHelper.setZenMode(mode, "NotificationManager");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void notifyConditions(String pkg, IConditionProvider provider,
Condition[] conditions) {
final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider);
@@ -1493,13 +1508,13 @@
@Override
public void requestZenModeConditions(IConditionListener callback, int relevance) {
- enforceSystemOrSystemUI("INotificationManager.requestZenModeConditions");
+ enforceSystemOrSystemUIOrVolume("INotificationManager.requestZenModeConditions");
mConditionProviders.requestZenModeConditions(callback, relevance);
}
@Override
public void setZenModeCondition(Condition condition) {
- enforceSystemOrSystemUI("INotificationManager.setZenModeCondition");
+ enforceSystemOrSystemUIOrVolume("INotificationManager.setZenModeCondition");
final long identity = Binder.clearCallingIdentity();
try {
mConditionProviders.setZenModeCondition(condition, "binderCall");
@@ -1520,6 +1535,16 @@
return mConditionProviders.getAutomaticZenModeConditions();
}
+ private void enforceSystemOrSystemUIOrVolume(String message) {
+ if (mAudioManagerInternal != null) {
+ final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
+ if (vcuid > 0 && Binder.getCallingUid() == vcuid) {
+ return;
+ }
+ }
+ enforceSystemOrSystemUI(message);
+ }
+
private void enforceSystemOrSystemUI(String message) {
if (isCallerSystem()) return;
getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -1541,7 +1566,7 @@
@Override
public ComponentName getEffectsSuppressor() {
- enforceSystemOrSystemUI("INotificationManager.getEffectsSuppressor");
+ enforceSystemOrSystemUIOrVolume("INotificationManager.getEffectsSuppressor");
return mEffectsSuppressor;
}
@@ -1558,7 +1583,7 @@
@Override
public boolean isSystemConditionProviderEnabled(String path) {
- enforceSystemOrSystemUI("INotificationManager.isSystemConditionProviderEnabled");
+ enforceSystemOrSystemUIOrVolume("INotificationManager.isSystemConditionProviderEnabled");
return mConditionProviders.isSystemConditionProviderEnabled(path);
}
};
@@ -1671,6 +1696,7 @@
if (filter == null || zenOnly) {
pw.println("\n Zen Mode:");
+ pw.print(" mInterruptionFilter="); pw.println(mInterruptionFilter);
mZenModeHelper.dump(pw, " ");
pw.println("\n Zen Log:");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 69a1ac9..2729392 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -28,7 +28,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -36,6 +35,7 @@
import android.os.Handler;
import android.os.IUserManager;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -111,6 +111,7 @@
private static final String USER_INFO_DIR = "system" + File.separator + "users";
private static final String USER_LIST_FILENAME = "userlist.xml";
private static final String USER_PHOTO_FILENAME = "photo.png";
+ private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp";
private static final String RESTRICTIONS_FILE_PREFIX = "res_";
private static final String XML_SUFFIX = ".xml";
@@ -433,7 +434,8 @@
}
@Override
- public Bitmap getUserIcon(int userId) {
+ public ParcelFileDescriptor getUserIcon(int userId) {
+ String iconPath;
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
@@ -448,8 +450,16 @@
if (info.iconPath == null) {
return null;
}
- return BitmapFactory.decodeFile(info.iconPath);
+ iconPath = info.iconPath;
}
+
+ try {
+ return ParcelFileDescriptor.open(
+ new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find icon file", e);
+ }
+ return null;
}
public void makeInitialized(int userId) {
@@ -572,6 +582,7 @@
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
File file = new File(dir, USER_PHOTO_FILENAME);
+ File tmp = new File(dir, USER_PHOTO_FILENAME_TMP);
if (!dir.exists()) {
dir.mkdir();
FileUtils.setPermissions(
@@ -580,7 +591,8 @@
-1, -1);
}
FileOutputStream os;
- if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
+ if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
+ && tmp.renameTo(file)) {
info.iconPath = file.getAbsolutePath();
}
try {
@@ -588,6 +600,7 @@
} catch (IOException ioe) {
// What the ... !
}
+ tmp.delete();
} catch (FileNotFoundException e) {
Slog.w(LOG_TAG, "Error setting photo for user ", e);
}
@@ -1787,7 +1800,8 @@
public int getUserHandle(int userSerialNumber) {
synchronized (mPackagesLock) {
for (int userId : mUserIds) {
- if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
+ UserInfo info = getUserInfoLocked(userId);
+ if (info != null && info.serialNumber == userSerialNumber) return userId;
}
// Not found
return -1;
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index bca2c16..e972ec7 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -43,15 +43,15 @@
private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
- private final String mTag;
+ protected final String mTag;
private final int mTransientFlag;
private final int mUnhideFlag;
private final int mTranslucentFlag;
private final int mStatusBarManagerId;
private final int mTranslucentWmFlag;
- private final Handler mHandler;
+ protected final Handler mHandler;
private final Object mServiceAquireLock = new Object();
- private IStatusBarService mStatusBarService;
+ protected IStatusBarService mStatusBarService;
private WindowState mWin;
private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
@@ -254,7 +254,7 @@
}
}
- private IStatusBarService getStatusBarService() {
+ protected IStatusBarService getStatusBarService() {
synchronized (mServiceAquireLock) {
if (mStatusBarService == null) {
mStatusBarService = IStatusBarService.Stub.asInterface(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ec8a77513..f691b4e 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -74,6 +74,7 @@
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -103,6 +104,8 @@
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.view.animation.TranslateAnimation;
import com.android.internal.R;
import com.android.internal.statusbar.IStatusBarService;
@@ -457,6 +460,7 @@
static final Rect mTmpNavigationFrame = new Rect();
WindowState mTopFullscreenOpaqueWindowState;
+ WindowState mTopFullscreenOpaqueOrDimmingWindowState;
HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
boolean mTopIsFullscreen;
@@ -723,12 +727,7 @@
}
MyOrientationListener mOrientationListener;
- private final BarController mStatusBarController = new BarController("StatusBar",
- View.STATUS_BAR_TRANSIENT,
- View.STATUS_BAR_UNHIDE,
- View.STATUS_BAR_TRANSLUCENT,
- StatusBarManager.WINDOW_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ private final StatusBarController mStatusBarController = new StatusBarController();
private final BarController mNavigationBarController = new BarController("NavigationBar",
View.NAVIGATION_BAR_TRANSIENT,
@@ -1195,8 +1194,7 @@
} catch (RemoteException ex) { }
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
- mShortcutManager = new ShortcutManager(context, mHandler);
- mShortcutManager.observe();
+ mShortcutManager = new ShortcutManager(context);
mUiMode = context.getResources().getInteger(
com.android.internal.R.integer.config_defaultUiModeType);
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
@@ -1359,6 +1357,9 @@
if (!mPowerManager.isInteractive()) {
goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}
+
+ mWindowManagerInternal.registerAppTransitionListener(
+ mStatusBarController.getAppTransitionListener());
}
/**
@@ -3555,7 +3556,7 @@
pf.bottom = df.bottom = of.bottom = cf.bottom
= mOverscanScreenTop + mOverscanScreenHeight;
}
- } else if (attrs.type == TYPE_INPUT_METHOD) {
+ } else if (attrs.type == TYPE_INPUT_METHOD || attrs.type == TYPE_VOICE_INTERACTION) {
pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
@@ -3937,7 +3938,7 @@
}
private void offsetInputMethodWindowLw(WindowState win) {
- int top = win.getContentFrameLw().top;
+ int top = win.getDisplayFrameLw().top;
top += win.getGivenContentInsetsLw().top;
if (mContentBottom > top) {
mContentBottom = top;
@@ -3956,36 +3957,10 @@
}
private void offsetVoiceInputWindowLw(WindowState win) {
- final int gravity = win.getAttrs().gravity;
- switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
- << Gravity.AXIS_X_SHIFT)) {
- case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_X_SHIFT: {
- int right = win.getContentFrameLw().right - win.getGivenContentInsetsLw().right;
- if (mVoiceContentLeft < right) {
- mVoiceContentLeft = right;
- }
- } break;
- case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_X_SHIFT: {
- int left = win.getContentFrameLw().left - win.getGivenContentInsetsLw().left;
- if (mVoiceContentRight < left) {
- mVoiceContentRight = left;
- }
- } break;
- }
- switch (gravity&((Gravity.AXIS_PULL_BEFORE|Gravity.AXIS_PULL_AFTER)
- << Gravity.AXIS_Y_SHIFT)) {
- case Gravity.AXIS_PULL_BEFORE<<Gravity.AXIS_Y_SHIFT: {
- int bottom = win.getContentFrameLw().bottom - win.getGivenContentInsetsLw().bottom;
- if (mVoiceContentTop < bottom) {
- mVoiceContentTop = bottom;
- }
- } break;
- case Gravity.AXIS_PULL_AFTER<<Gravity.AXIS_Y_SHIFT: {
- int top = win.getContentFrameLw().top - win.getGivenContentInsetsLw().top;
- if (mVoiceContentBottom < top) {
- mVoiceContentBottom = top;
- }
- } break;
+ int top = win.getDisplayFrameLw().top;
+ top += win.getGivenContentInsetsLw().top;
+ if (mVoiceContentBottom > top) {
+ mVoiceContentBottom = top;
}
}
@@ -3999,6 +3974,7 @@
@Override
public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
mTopFullscreenOpaqueWindowState = null;
+ mTopFullscreenOpaqueOrDimmingWindowState = null;
mAppsToBeHidden.clear();
mAppsThatDismissKeyguard.clear();
mForceStatusBar = false;
@@ -4087,6 +4063,9 @@
&& attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
+ if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
+ mTopFullscreenOpaqueOrDimmingWindowState = win;
+ }
if (!mAppsThatDismissKeyguard.isEmpty() &&
mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
if (DEBUG_LAYOUT) Slog.v(TAG,
@@ -4112,6 +4091,11 @@
}
}
}
+ if (mTopFullscreenOpaqueOrDimmingWindowState == null
+ && win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()
+ && win.isDimming()) {
+ mTopFullscreenOpaqueOrDimmingWindowState = win;
+ }
}
/** {@inheritDoc} */
@@ -4751,7 +4735,6 @@
msg.setAsynchronous(true);
msg.sendToTarget();
}
- break;
}
}
@@ -6079,6 +6062,7 @@
if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
+ tmpVisibility = updateLightStatusBarLw(tmpVisibility);
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
@@ -6107,6 +6091,26 @@
return diff;
}
+ private int updateLightStatusBarLw(int vis) {
+ WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
+ ? mStatusBar
+ : mTopFullscreenOpaqueOrDimmingWindowState;
+
+ if (statusColorWin != null) {
+ if (statusColorWin == mTopFullscreenOpaqueWindowState) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+ & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ } else if (statusColorWin != null && statusColorWin.isDimming()) {
+ // Otherwise if it's dimming, clear the light flag.
+ vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ }
+ }
+ return vis;
+ }
+
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
// apply translucent bar vis flags
WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -6121,7 +6125,8 @@
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
if (mHideLockScreen) {
flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
}
@@ -6387,9 +6392,8 @@
}
if (mStatusBar != null) {
pw.print(prefix); pw.print("mStatusBar=");
- pw.println(mStatusBar);
- pw.print(prefix); pw.print("isStatusBarKeyguard=");
- pw.print(isStatusBarKeyguard());
+ pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
+ pw.println(isStatusBarKeyguard());
}
if (mNavigationBar != null) {
pw.print(prefix); pw.print("mNavigationBar=");
@@ -6411,6 +6415,10 @@
pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
pw.println(mTopFullscreenOpaqueWindowState);
}
+ if (mTopFullscreenOpaqueOrDimmingWindowState != null) {
+ pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState=");
+ pw.println(mTopFullscreenOpaqueOrDimmingWindowState);
+ }
if (mForcingShowNavBar) {
pw.print(prefix); pw.print("mForcingShowNavBar=");
pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer=");
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 6a0136a..76f56bc 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -16,81 +16,47 @@
package com.android.server.policy;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.os.Handler;
-import android.provider.Settings;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyCharacterMap;
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
-import java.net.URISyntaxException;
+import java.io.IOException;
/**
* Manages quick launch shortcuts by:
* <li> Keeping the local copy in sync with the database (this is an observer)
* <li> Returning a shortcut-matching intent to clients
*/
-class ShortcutManager extends ContentObserver {
-
+class ShortcutManager {
private static final String TAG = "ShortcutManager";
-
- private static final int COLUMN_SHORTCUT = 0;
- private static final int COLUMN_INTENT = 1;
- private static final String[] sProjection = new String[] {
- Settings.Bookmarks.SHORTCUT, Settings.Bookmarks.INTENT
- };
- private Context mContext;
- private Cursor mCursor;
- /** Map of a shortcut to its intent. */
- private SparseArray<Intent> mShortcutIntents;
+ private static final String TAG_BOOKMARKS = "bookmarks";
+ private static final String TAG_BOOKMARK = "bookmark";
+
+ private static final String ATTRIBUTE_PACKAGE = "package";
+ private static final String ATTRIBUTE_CLASS = "class";
+ private static final String ATTRIBUTE_SHORTCUT = "shortcut";
+ private static final String ATTRIBUTE_CATEGORY = "category";
+
+ private final SparseArray<ShortcutInfo> mShortcuts = new SparseArray<>();
+
+ private final Context mContext;
- public ShortcutManager(Context context, Handler handler) {
- super(handler);
-
+ public ShortcutManager(Context context) {
mContext = context;
- mShortcutIntents = new SparseArray<Intent>();
+ loadShortcuts();
}
- /** Observes the provider of shortcut+intents */
- public void observe() {
- mCursor = mContext.getContentResolver().query(
- Settings.Bookmarks.CONTENT_URI, sProjection, null, null, null);
- mCursor.registerContentObserver(this);
- updateShortcuts();
- }
-
- @Override
- public void onChange(boolean selfChange) {
- updateShortcuts();
- }
-
- private void updateShortcuts() {
- Cursor c = mCursor;
- if (!c.requery()) {
- Log.e(TAG, "ShortcutObserver could not re-query shortcuts.");
- return;
- }
-
- mShortcutIntents.clear();
- while (c.moveToNext()) {
- int shortcut = c.getInt(COLUMN_SHORTCUT);
- if (shortcut == 0) continue;
- String intentURI = c.getString(COLUMN_INTENT);
- Intent intent = null;
- try {
- intent = Intent.getIntent(intentURI);
- } catch (URISyntaxException e) {
- Log.w(TAG, "Intent URI for shortcut invalid.", e);
- }
- if (intent == null) continue;
- mShortcutIntents.put(shortcut, intent);
- }
- }
-
/**
* Gets the shortcut intent for a given keycode+modifier. Make sure you
* strip whatever modifier is used for invoking shortcuts (for example,
@@ -107,23 +73,105 @@
* @return The intent that matches the shortcut, or null if not found.
*/
public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
- Intent intent = null;
+ ShortcutInfo shortcut = null;
// First try the exact keycode (with modifiers).
- int shortcut = kcm.get(keyCode, metaState);
- if (shortcut != 0) {
- intent = mShortcutIntents.get(shortcut);
+ int shortcutChar = kcm.get(keyCode, metaState);
+ if (shortcutChar != 0) {
+ shortcut = mShortcuts.get(shortcutChar);
}
// Next try the primary character on that key.
- if (intent == null) {
- shortcut = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
- if (shortcut != 0) {
- intent = mShortcutIntents.get(shortcut);
+ if (shortcut == null) {
+ shortcutChar = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
+ if (shortcutChar != 0) {
+ shortcut = mShortcuts.get(shortcutChar);
}
}
- return intent;
+ return (shortcut != null) ? shortcut.intent : null;
}
+ private void loadShortcuts() {
+ PackageManager packageManager = mContext.getPackageManager();
+ try {
+ XmlResourceParser parser = mContext.getResources().getXml(
+ com.android.internal.R.xml.bookmarks);
+ XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+
+ if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
+ break;
+ }
+
+ if (!TAG_BOOKMARK.equals(parser.getName())) {
+ break;
+ }
+
+ String packageName = parser.getAttributeValue(null, ATTRIBUTE_PACKAGE);
+ String className = parser.getAttributeValue(null, ATTRIBUTE_CLASS);
+ String shortcutName = parser.getAttributeValue(null, ATTRIBUTE_SHORTCUT);
+ String categoryName = parser.getAttributeValue(null, ATTRIBUTE_CATEGORY);
+
+ if (TextUtils.isEmpty(shortcutName)) {
+ Log.w(TAG, "Unable to get shortcut for: " + packageName + "/" + className);
+ continue;
+ }
+
+ final int shortcutChar = shortcutName.charAt(0);
+
+ final Intent intent;
+ final String title;
+ if (packageName != null && className != null) {
+ ActivityInfo info = null;
+ ComponentName componentName = new ComponentName(packageName, className);
+ try {
+ info = packageManager.getActivityInfo(componentName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ String[] packages = packageManager.canonicalToCurrentPackageNames(
+ new String[] { packageName });
+ componentName = new ComponentName(packages[0], className);
+ try {
+ info = packageManager.getActivityInfo(componentName, 0);
+ } catch (PackageManager.NameNotFoundException e1) {
+ Log.w(TAG, "Unable to add bookmark: " + packageName
+ + "/" + className, e);
+ continue;
+ }
+ }
+
+ intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ intent.setComponent(componentName);
+ title = info.loadLabel(packageManager).toString();
+ } else if (categoryName != null) {
+ intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, categoryName);
+ title = "";
+ } else {
+ Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutName
+ + ": missing package/class or category attributes");
+ continue;
+ }
+
+ ShortcutInfo shortcut = new ShortcutInfo(title, intent);
+ mShortcuts.put(shortcutChar, shortcut);
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Got exception parsing bookmarks.", e);
+ } catch (IOException e) {
+ Log.w(TAG, "Got exception parsing bookmarks.", e);
+ }
+ }
+
+ private static final class ShortcutInfo {
+ public final String title;
+ public final Intent intent;
+
+ public ShortcutInfo(String title, Intent intent) {
+ this.title = title;
+ this.intent = intent;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
new file mode 100644
index 0000000..4d4ab44
--- /dev/null
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.policy;
+
+import android.app.StatusBarManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerInternal;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.Interpolator;
+import android.view.animation.TranslateAnimation;
+
+import com.android.internal.statusbar.IStatusBarService;
+
+import static android.view.WindowManagerInternal.*;
+
+/**
+ * Implements status bar specific behavior.
+ */
+public class StatusBarController extends BarController {
+
+ private static final long TRANSITION_DURATION = 120L;
+
+ private final AppTransitionListener mAppTransitionListener
+ = new AppTransitionListener() {
+
+ @Override
+ public void onAppTransitionPendingLocked() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ statusbar.appTransitionPending();
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is pending", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAppTransitionStartingLocked(IBinder openToken, IBinder closeToken,
+ final Animation openAnimation, final Animation closeAnimation) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ long startTime = calculateStatusBarTransitionStartTime(openAnimation,
+ closeAnimation);
+ statusbar.appTransitionStarting(startTime, TRANSITION_DURATION);
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is starting", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAppTransitionCancelledLocked() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ statusbar.appTransitionCancelled();
+ }
+ } catch (RemoteException e) {
+ Slog.e(mTag, "RemoteException when app transition is cancelled", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
+ }
+ });
+ }
+ };
+
+ public StatusBarController() {
+ super("StatusBar",
+ View.STATUS_BAR_TRANSIENT,
+ View.STATUS_BAR_UNHIDE,
+ View.STATUS_BAR_TRANSLUCENT,
+ StatusBarManager.WINDOW_STATUS_BAR,
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ }
+
+ public AppTransitionListener getAppTransitionListener() {
+ return mAppTransitionListener;
+ }
+
+ /**
+ * For a given app transition with {@code openAnimation} and {@code closeAnimation}, this
+ * calculates the timings for the corresponding status bar transition.
+ *
+ * @return the desired start time of the status bar transition, in uptime millis
+ */
+ private long calculateStatusBarTransitionStartTime(Animation openAnimation,
+ Animation closeAnimation) {
+ if (openAnimation != null && closeAnimation != null) {
+ TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
+ TranslateAnimation closeTranslateAnimation = findTranslateAnimation(closeAnimation);
+ if (openTranslateAnimation != null) {
+
+ // Some interpolators are extremely quickly mostly finished, but not completely. For
+ // our purposes, we need to find the fraction for which ther interpolator is mostly
+ // there, and use that value for the calculation.
+ float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
+ return SystemClock.uptimeMillis()
+ + openTranslateAnimation.getStartOffset()
+ + (long)(openTranslateAnimation.getDuration()*t) - TRANSITION_DURATION;
+ } else if (closeTranslateAnimation != null) {
+ return SystemClock.uptimeMillis();
+ } else {
+ return SystemClock.uptimeMillis();
+ }
+ } else {
+ return SystemClock.uptimeMillis();
+ }
+ }
+
+ /**
+ * Tries to find a {@link TranslateAnimation} inside the {@code animation}.
+ *
+ * @return the found animation, {@code null} otherwise
+ */
+ private TranslateAnimation findTranslateAnimation(Animation animation) {
+ if (animation instanceof TranslateAnimation) {
+ return (TranslateAnimation) animation;
+ } else if (animation instanceof AnimationSet) {
+ AnimationSet set = (AnimationSet) animation;
+ for (int i = 0; i < set.getAnimations().size(); i++) {
+ Animation a = set.getAnimations().get(i);
+ if (a instanceof TranslateAnimation) {
+ return (TranslateAnimation) a;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
+ * {@code interpolator(t + eps) > 0.99}.
+ */
+ private float findAlmostThereFraction(Interpolator interpolator) {
+ float val = 0.5f;
+ float adj = 0.25f;
+ while (adj >= 0.01f) {
+ if (interpolator.getInterpolation(val) < 0.99f) {
+ val += adj;
+ } else {
+ val -= adj;
+ }
+ adj /= 2;
+ }
+ return val;
+ }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9786b42..66c2f5f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -128,6 +128,7 @@
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
private static final int WAKE_LOCK_DOZE = 1 << 6;
+ private static final int WAKE_LOCK_DRAW = 1 << 7;
// Summarizes the user activity state.
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
@@ -1398,12 +1399,15 @@
case PowerManager.DOZE_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
+ case PowerManager.DRAW_WAKE_LOCK:
+ mWakeLockSummary |= WAKE_LOCK_DRAW;
+ break;
}
}
// Cancel wake locks that make no sense based on the current state.
if (mWakefulness != WAKEFULNESS_DOZING) {
- mWakeLockSummary &= ~WAKE_LOCK_DOZE;
+ mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
if (mWakefulness == WAKEFULNESS_ASLEEP
|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
@@ -1422,6 +1426,9 @@
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
+ if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
+ mWakeLockSummary |= WAKE_LOCK_CPU;
+ }
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
@@ -1845,6 +1852,10 @@
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
+ if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
+ && (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
+ mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+ }
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
} else {
@@ -2712,6 +2723,8 @@
return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
case PowerManager.DOZE_WAKE_LOCK:
return "DOZE_WAKE_LOCK ";
+ case PowerManager.DRAW_WAKE_LOCK:
+ return "DRAW_WAKE_LOCK ";
default:
return "??? ";
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index cf2ed07..f6df757 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -454,6 +454,35 @@
}
}
+ @Override
+ public void appTransitionPending() {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionPending();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionCancelled();
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void appTransitionStarting(long statusBarAnimationsStartTime,
+ long statusBarAnimationsDuration) {
+ if (mBar != null) {
+ try {
+ mBar.appTransitionStarting(
+ statusBarAnimationsStartTime, statusBarAnimationsDuration);
+ } catch (RemoteException ex) {}
+ }
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
@@ -625,7 +654,6 @@
}
}
-
// ================================================================================
// Can be called from any thread
// ================================================================================
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 50b2262..c5f4161 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -699,15 +699,14 @@
private void findAudioSinkFromAudioPolicy(List<AudioDevicePort> sinks) {
sinks.clear();
- ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
+ ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>();
if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) {
return;
}
int sinkDevice = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
- for (AudioPort port : devicePorts) {
- AudioDevicePort devicePort = (AudioDevicePort) port;
- if ((devicePort.type() & sinkDevice) != 0) {
- sinks.add(devicePort);
+ for (AudioDevicePort port : devicePorts) {
+ if ((port.type() & sinkDevice) != 0) {
+ sinks.add(port);
}
}
}
@@ -716,14 +715,13 @@
if (type == AudioManager.DEVICE_NONE) {
return null;
}
- ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
+ ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>();
if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) {
return null;
}
- for (AudioPort port : devicePorts) {
- AudioDevicePort devicePort = (AudioDevicePort) port;
- if (devicePort.type() == type && devicePort.address().equals(address)) {
- return devicePort;
+ for (AudioDevicePort port : devicePorts) {
+ if (port.type() == type && port.address().equals(address)) {
+ return port;
}
}
return null;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index f8b40d1..b5d4caf 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -397,8 +397,6 @@
private final class MagnifiedViewport {
- private static final int DEFAUTLT_BORDER_WIDTH_DIP = 5;
-
private final SparseArray<WindowState> mTempWindowStates =
new SparseArray<WindowState>();
@@ -411,6 +409,8 @@
private final Region mMagnifiedBounds = new Region();
private final Region mOldMagnifiedBounds = new Region();
+ private final Path mCircularPath;
+
private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain();
private final WindowManager mWindowManager;
@@ -425,12 +425,22 @@
public MagnifiedViewport() {
mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE);
- mBorderWidth = TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, DEFAUTLT_BORDER_WIDTH_DIP,
- mContext.getResources().getDisplayMetrics());
+ mBorderWidth = mContext.getResources().getDimension(
+ com.android.internal.R.dimen.accessibility_magnification_indicator_width);
mHalfBorderWidth = (int) Math.ceil(mBorderWidth / 2);
mDrawBorderInset = (int) mBorderWidth / 2;
mWindow = new ViewportWindow(mContext);
+
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_windowIsRound)) {
+ mCircularPath = new Path();
+ mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ final int centerXY = mTempPoint.x / 2;
+ mCircularPath.addCircle(centerXY, centerXY, centerXY, Path.Direction.CW);
+ } else {
+ mCircularPath = null;
+ }
+
recomputeBoundsLocked();
}
@@ -459,6 +469,10 @@
Region availableBounds = mTempRegion1;
availableBounds.set(0, 0, screenWidth, screenHeight);
+ if (mCircularPath != null) {
+ availableBounds.setPath(mCircularPath, availableBounds);
+ }
+
Region nonMagnifiedBounds = mTempRegion4;
nonMagnifiedBounds.set(0, 0, 0, 0);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c0d54e1..ef70895 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -22,6 +22,7 @@
import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
import android.util.Slog;
import android.view.WindowManager;
@@ -30,15 +31,22 @@
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.ClipRectAnimation;
+import android.view.animation.ClipRectLRAnimation;
+import android.view.animation.ClipRectTBAnimation;
import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
+import android.view.animation.TranslateXAnimation;
+import android.view.animation.TranslateYAnimation;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import static android.view.WindowManagerInternal.AppTransitionListener;
import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
@@ -134,6 +142,7 @@
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7;
+ private static final int NEXT_TRANSIT_TYPE_CLIP_REVEAL = 8;
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
// These are the possible states for the enter/exit activities during a thumbnail transition
@@ -169,19 +178,26 @@
private final Interpolator mDecelerateInterpolator;
private final Interpolator mThumbnailFadeInInterpolator;
private final Interpolator mThumbnailFadeOutInterpolator;
- private final Interpolator mThumbnailFastOutSlowInInterpolator;
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final Interpolator mFastOutSlowInInterpolator;
+ private final LinearInterpolator mLinearInterpolator;
private int mCurrentUserId = 0;
+ private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
+
AppTransition(Context context, Handler h) {
mContext = context;
mH = h;
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.linear_out_slow_in);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_slow_in);
+ mLinearInterpolator = new LinearInterpolator();
mConfigShortAnimTime = context.getResources().getInteger(
com.android.internal.R.integer.config_shortAnimTime);
mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.decelerate_cubic);
- mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
- com.android.internal.R.interpolator.fast_out_slow_in);
mThumbnailFadeInInterpolator = new Interpolator() {
@Override
public float getInterpolation(float input) {
@@ -276,12 +292,18 @@
void prepare() {
if (!isRunning()) {
mAppTransitionState = APP_STATE_IDLE;
+ notifyAppTransitionPendingLocked();
}
}
- void goodToGo() {
+ void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) {
mNextAppTransition = TRANSIT_UNSET;
mAppTransitionState = APP_STATE_RUNNING;
+ notifyAppTransitionStartingLocked(
+ openingAppAnimator != null ? openingAppAnimator.mAppToken.token : null,
+ closingAppAnimator != null ? closingAppAnimator.mAppToken.token : null,
+ openingAppAnimator != null ? openingAppAnimator.animation : null,
+ closingAppAnimator != null ? closingAppAnimator.animation : null);
}
void clear() {
@@ -294,6 +316,38 @@
setAppTransition(AppTransition.TRANSIT_UNSET);
clear();
setReady();
+ notifyAppTransitionCancelledLocked();
+ }
+
+ void registerListenerLocked(AppTransitionListener listener) {
+ mListeners.add(listener);
+ }
+
+ public void notifyAppTransitionFinishedLocked(AppWindowAnimator animator) {
+ IBinder token = animator != null ? animator.mAppToken.token : null;
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAppTransitionFinishedLocked(token);
+ }
+ }
+
+ private void notifyAppTransitionPendingLocked() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAppTransitionPendingLocked();
+ }
+ }
+
+ private void notifyAppTransitionCancelledLocked() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAppTransitionCancelledLocked();
+ }
+ }
+
+ private void notifyAppTransitionStartingLocked(IBinder openToken,
+ IBinder closeToken, Animation openAnimation, Animation closeAnimation) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAppTransitionStartingLocked(openToken, closeToken, openAnimation,
+ closeAnimation);
+ }
}
private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
@@ -447,6 +501,83 @@
return a;
}
+ private Animation createClipRevealAnimationLocked(int transit, boolean enter,
+ int appWidth, int appHeight) {
+ final Animation anim;
+ if (enter) {
+ // Reveal will expand and move faster in horizontal direction
+
+ // Start from size of launch icon, expand to full width/height
+ Animation clipAnimLR = new ClipRectLRAnimation(
+ (appWidth - mNextAppTransitionStartWidth) / 2,
+ (appWidth + mNextAppTransitionStartWidth) / 2, 0, appWidth);
+ clipAnimLR.setInterpolator(mLinearOutSlowInInterpolator);
+ clipAnimLR.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ Animation clipAnimTB = new ClipRectTBAnimation(
+ (appHeight - mNextAppTransitionStartHeight) / 2,
+ (appHeight + mNextAppTransitionStartHeight) / 2, 0, appHeight);
+ clipAnimTB.setInterpolator(mFastOutSlowInInterpolator);
+ clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+
+ // Start from middle of launch icon area, move to 0, 0
+ int startMiddleX = mNextAppTransitionStartX +
+ (mNextAppTransitionStartWidth - appWidth) / 2;
+ int startMiddleY = mNextAppTransitionStartY +
+ (mNextAppTransitionStartHeight - appHeight) / 2;
+
+ TranslateXAnimation translateX = new TranslateXAnimation(
+ Animation.ABSOLUTE, startMiddleX, Animation.ABSOLUTE, 0);
+ translateX.setInterpolator(mLinearOutSlowInInterpolator);
+ translateX.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ TranslateYAnimation translateY = new TranslateYAnimation(
+ Animation.ABSOLUTE, startMiddleY, Animation.ABSOLUTE, 0);
+ translateY.setInterpolator(mFastOutSlowInInterpolator);
+ translateY.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+
+ // Quick fade-in from icon to app window
+ final int alphaDuration = 100;
+ AlphaAnimation alpha = new AlphaAnimation(0.1f, 1);
+ alpha.setDuration(alphaDuration);
+ alpha.setInterpolator(mLinearInterpolator);
+
+ AnimationSet set = new AnimationSet(false);
+ set.addAnimation(clipAnimLR);
+ set.addAnimation(clipAnimTB);
+ set.addAnimation(translateX);
+ set.addAnimation(translateY);
+ set.addAnimation(alpha);
+ set.initialize(appWidth, appHeight, appWidth, appHeight);
+ anim = set;
+ } else {
+ final long duration;
+ switch (transit) {
+ case TRANSIT_ACTIVITY_OPEN:
+ case TRANSIT_ACTIVITY_CLOSE:
+ duration = mConfigShortAnimTime;
+ break;
+ default:
+ duration = DEFAULT_APP_TRANSITION_DURATION;
+ break;
+ }
+ if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
+ transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
+ // If we are on top of the wallpaper, we need an animation that
+ // correctly handles the wallpaper staying static behind all of
+ // the animated elements. To do this, will just have the existing
+ // element fade out.
+ anim = new AlphaAnimation(1, 0);
+ anim.setDetachWallpaper(true);
+ } else {
+ // For normal animations, the exiting element just holds in place.
+ anim = new AlphaAnimation(1, 1);
+ }
+ anim.setInterpolator(mDecelerateInterpolator);
+ anim.setDuration(duration);
+ anim.setFillAfter(true);
+ }
+ return anim;
+ }
+
/**
* Prepares the specified animation with a standard duration, interpolator, etc.
*/
@@ -522,14 +653,14 @@
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
mNextAppTransitionStartX + (thumbWidth / 2f),
mNextAppTransitionStartY + (thumbHeight / 2f));
- scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setInterpolator(mFastOutSlowInInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1, 0);
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY +
mNextAppTransitionInsets.top);
- translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setInterpolator(mFastOutSlowInInterpolator);
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
@@ -543,14 +674,14 @@
Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
mNextAppTransitionStartX + (thumbWidth / 2f),
mNextAppTransitionStartY + (thumbHeight / 2f));
- scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setInterpolator(mFastOutSlowInInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(0f, 1f);
alpha.setInterpolator(mThumbnailFadeInInterpolator);
alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
Animation translate = new TranslateAnimation(0, 0, -unscaledStartY +
mNextAppTransitionInsets.top, 0);
- translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setInterpolator(mFastOutSlowInInterpolator);
translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
@@ -562,7 +693,7 @@
}
return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0,
- mThumbnailFastOutSlowInInterpolator);
+ mFastOutSlowInInterpolator);
}
/**
@@ -698,7 +829,7 @@
int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
THUMBNAIL_APP_TRANSITION_DURATION);
return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
- mThumbnailFastOutSlowInInterpolator);
+ mFastOutSlowInInterpolator);
}
/**
@@ -845,6 +976,12 @@
"applyAnimation:"
+ " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE"
+ " transit=" + transit + " Callers=" + Debug.getCallers(3));
+ } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
+ a = createClipRevealAnimationLocked(transit, enter, appWidth, appHeight);
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+ "applyAnimation:"
+ + " anim=" + a + " nextAppTransition=ANIM_CLIP_REVEAL"
+ + " Callers=" + Debug.getCallers(3));
} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
a = createScaleUpAnimationLocked(transit, enter, appWidth, appHeight);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
@@ -987,6 +1124,19 @@
}
}
+ void overridePendingAppTransitionClipReveal(int startX, int startY,
+ int startWidth, int startHeight) {
+ if (isTransitionSet()) {
+ mNextAppTransitionType = NEXT_TRANSIT_TYPE_CLIP_REVEAL;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ mNextAppTransitionStartWidth = startWidth;
+ mNextAppTransitionStartHeight = startHeight;
+ postAnimationCallback();
+ mNextAppTransitionCallback = null;
+ }
+ }
+
void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp) {
if (isTransitionSet()) {
@@ -1130,32 +1280,34 @@
}
@Override
- public void dump(PrintWriter pw) {
- pw.print(" " + this);
- pw.print(" mAppTransitionState="); pw.println(appStateToString());
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println(this);
+ pw.print(prefix); pw.print("mAppTransitionState="); pw.println(appStateToString());
if (mNextAppTransitionType != NEXT_TRANSIT_TYPE_NONE) {
- pw.print(" mNextAppTransitionType="); pw.println(transitTypeToString());
+ pw.print(prefix); pw.print("mNextAppTransitionType=");
+ pw.println(transitTypeToString());
}
switch (mNextAppTransitionType) {
case NEXT_TRANSIT_TYPE_CUSTOM:
- pw.print(" mNextAppTransitionPackage=");
+ pw.print(prefix); pw.print("mNextAppTransitionPackage=");
pw.println(mNextAppTransitionPackage);
- pw.print(" mNextAppTransitionEnter=0x");
+ pw.print(prefix); pw.print("mNextAppTransitionEnter=0x");
pw.print(Integer.toHexString(mNextAppTransitionEnter));
pw.print(" mNextAppTransitionExit=0x");
pw.println(Integer.toHexString(mNextAppTransitionExit));
break;
case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE:
- pw.print(" mNextAppTransitionPackage=");
+ pw.print(prefix); pw.print("mNextAppTransitionPackage=");
pw.println(mNextAppTransitionPackage);
- pw.print(" mNextAppTransitionInPlace=0x");
+ pw.print(prefix); pw.print("mNextAppTransitionInPlace=0x");
pw.print(Integer.toHexString(mNextAppTransitionInPlace));
break;
case NEXT_TRANSIT_TYPE_SCALE_UP:
- pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
+ pw.print(prefix); pw.print("mNextAppTransitionStartX=");
+ pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY=");
pw.println(mNextAppTransitionStartY);
- pw.print(" mNextAppTransitionStartWidth=");
+ pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
pw.print(mNextAppTransitionStartWidth);
pw.print(" mNextAppTransitionStartHeight=");
pw.println(mNextAppTransitionStartHeight);
@@ -1164,22 +1316,23 @@
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
- pw.print(" mNextAppTransitionThumbnail=");
+ pw.print(prefix); pw.print("mNextAppTransitionThumbnail=");
pw.print(mNextAppTransitionThumbnail);
pw.print(" mNextAppTransitionStartX=");
pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY=");
pw.println(mNextAppTransitionStartY);
- pw.print(" mNextAppTransitionStartWidth=");
+ pw.print(prefix); pw.print("mNextAppTransitionStartWidth=");
pw.print(mNextAppTransitionStartWidth);
pw.print(" mNextAppTransitionStartHeight=");
pw.println(mNextAppTransitionStartHeight);
- pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
+ pw.print(prefix); pw.print("mNextAppTransitionScaleUp=");
+ pw.println(mNextAppTransitionScaleUp);
break;
}
if (mNextAppTransitionCallback != null) {
- pw.print(" mNextAppTransitionCallback=");
- pw.println(mNextAppTransitionCallback);
+ pw.print(prefix); pw.print("mNextAppTransitionCallback=");
+ pw.println(mNextAppTransitionCallback);
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 5c81126..a58f30d 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import android.graphics.Matrix;
-import android.os.RemoteException;
import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
@@ -142,6 +141,10 @@
}
}
+ public boolean isAnimating() {
+ return animation != null || mAppToken.inPendingTransaction;
+ }
+
public void clearThumbnail() {
if (thumbnail != null) {
thumbnail.destroy();
@@ -312,23 +315,7 @@
for (int i = 0; i < numAllAppWinAnimators; i++) {
mAllAppWinAnimators.get(i).finishExit();
}
- if (mAppToken.mLaunchTaskBehind) {
- try {
- mService.mActivityManager.notifyLaunchTaskBehindComplete(mAppToken.token);
- } catch (RemoteException e) {
- }
- mAppToken.mLaunchTaskBehind = false;
- } else {
- mAppToken.updateReportedVisibilityLocked();
- if (mAppToken.mEnteringAnimation) {
- mAppToken.mEnteringAnimation = false;
- try {
- mService.mActivityManager.notifyEnterAnimationComplete(mAppToken.token);
- } catch (RemoteException e) {
- }
- }
- }
-
+ mService.mAppTransition.notifyAppTransitionFinishedLocked(this);
return false;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8bbc5a9..f073c23 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -241,23 +241,24 @@
mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
}
}
- mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
+ if (mTapDetector != null) {
+ mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
+ }
}
- void switchUserStacks(int newUserId) {
+ void switchUserStacks() {
final WindowList windows = getWindowList();
for (int i = 0; i < windows.size(); i++) {
final WindowState win = windows.get(i);
if (win.isHiddenFromUserLocked()) {
- if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "
- + win + ", attrs=" + win.mAttrs.type + ", belonging to "
- + win.mOwnerUid);
+ if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing, hiding " + win
+ + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
win.hideLw(false);
}
}
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- mStacks.get(stackNdx).switchUser(newUserId);
+ mStacks.get(stackNdx).switchUser();
}
}
@@ -340,6 +341,12 @@
}
}
+ static int deltaRotation(int oldRotation, int newRotation) {
+ int delta = newRotation - oldRotation;
+ if (delta < 0) delta += 4;
+ return delta;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
final String subPrefix = " " + prefix;
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index 62f2b48..5e4bd8b 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -93,7 +93,9 @@
}
c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
mSurfaceControl.setPosition(0, 0);
- mOverlay.setBounds(0, 0, mScreenSize.x, mScreenSize.y);
+ // Always draw the overlay with square dimensions
+ int size = Math.max(mScreenSize.x, mScreenSize.y);
+ mOverlay.setBounds(0, 0, size, size);
mOverlay.draw(c);
mSurface.unlockCanvasAndPost(c);
}
diff --git a/services/core/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedStackFrame.java
index f1f5fe8..826fe97 100644
--- a/services/core/java/com/android/server/wm/FocusedStackFrame.java
+++ b/services/core/java/com/android/server/wm/FocusedStackFrame.java
@@ -16,14 +16,14 @@
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
+import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.Region;
import android.util.Slog;
import android.view.Display;
import android.view.Surface.OutOfResourcesException;
@@ -35,14 +35,17 @@
class FocusedStackFrame {
private static final String TAG = "FocusedStackFrame";
- private static final int THICKNESS = 10;
+ private static final boolean DEBUG = false;
+ private static final int THICKNESS = 2;
private static final float ALPHA = 0.3f;
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
+ private final Paint mInnerPaint = new Paint();
+ private final Paint mOuterPaint = new Paint();
+ private final Rect mBounds = new Rect();
private final Rect mLastBounds = new Rect();
- final Rect mBounds = new Rect();
- private final Rect mTmpDrawRect = new Rect();
+ private int mLayer = -1;
public FocusedStackFrame(Display display, SurfaceSession session) {
SurfaceControl ctrl = null;
@@ -60,83 +63,84 @@
} catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
+
+ mInnerPaint.setStyle(Paint.Style.STROKE);
+ mInnerPaint.setStrokeWidth(THICKNESS);
+ mInnerPaint.setColor(Color.WHITE);
+ mOuterPaint.setStyle(Paint.Style.STROKE);
+ mOuterPaint.setStrokeWidth(THICKNESS);
+ mOuterPaint.setColor(Color.BLACK);
}
- private void draw(Rect bounds, int color) {
- if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() +
- " color=" + Integer.toHexString(color));
- mTmpDrawRect.set(bounds);
+ private void draw() {
+ if (mLastBounds.isEmpty()) {
+ // Currently unset. Set it.
+ mLastBounds.set(mBounds);
+ }
+
+ if (DEBUG) Slog.i(TAG, "draw: mBounds=" + mBounds + " mLastBounds=" + mLastBounds);
+
Canvas c = null;
try {
- c = mSurface.lockCanvas(mTmpDrawRect);
+ c = mSurface.lockCanvas(mLastBounds);
} catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Unable to lock canvas", e);
} catch (Surface.OutOfResourcesException e) {
+ Slog.e(TAG, "Unable to lock canvas", e);
}
if (c == null) {
+ if (DEBUG) Slog.w(TAG, "Canvas is null...");
return;
}
- final int w = bounds.width();
- final int h = bounds.height();
-
- // Top
- mTmpDrawRect.set(0, 0, w, THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Left (not including Top or Bottom stripe).
- mTmpDrawRect.set(0, THICKNESS, THICKNESS, h - THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Right (not including Top or Bottom stripe).
- mTmpDrawRect.set(w - THICKNESS, THICKNESS, w, h - THICKNESS);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
- // Bottom
- mTmpDrawRect.set(0, h - THICKNESS, w, h);
- c.clipRect(mTmpDrawRect, Region.Op.REPLACE);
- c.drawColor(color);
-
+ c.drawRect(0, 0, mBounds.width(), mBounds.height(), mOuterPaint);
+ c.drawRect(THICKNESS, THICKNESS, mBounds.width() - THICKNESS, mBounds.height() - THICKNESS,
+ mInnerPaint);
+ if (DEBUG) Slog.w(TAG, "c.width=" + c.getWidth() + " c.height=" + c.getHeight()
+ + " c.clip=" + c .getClipBounds());
mSurface.unlockCanvasAndPost(c);
+ mLastBounds.set(mBounds);
}
- private void positionSurface(Rect bounds) {
- if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString());
- mSurfaceControl.setSize(bounds.width(), bounds.height());
- mSurfaceControl.setPosition(bounds.left, bounds.top);
+ private void setupSurface(boolean visible) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setupSurface");
+ SurfaceControl.openTransaction();
+ try {
+ if (visible) {
+ mSurfaceControl.setPosition(mBounds.left, mBounds.top);
+ mSurfaceControl.setSize(mBounds.width(), mBounds.height());
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setupSurface");
+ }
+ }
+
+ void setVisibility(TaskStack stack) {
+ if (stack == null || stack.isFullscreen()) {
+ setupSurface(false);
+ } else {
+ stack.getBounds(mBounds);
+ setupSurface(true);
+ if (!mBounds.equals(mLastBounds)) {
+ draw();
+ }
+ }
}
// Note: caller responsible for being inside
// Surface.openTransaction() / closeTransaction()
- public void setVisibility(boolean on) {
- if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on +
- " mLastBounds=" + mLastBounds.toShortString() +
- " mBounds=" + mBounds.toShortString());
- if (mSurfaceControl == null) {
+ void setLayer(int layer) {
+ if (mLayer == layer) {
return;
}
- if (on) {
- if (!mLastBounds.equals(mBounds)) {
- // Erase the previous rectangle.
- positionSurface(mLastBounds);
- draw(mLastBounds, Color.TRANSPARENT);
- // Draw the latest rectangle.
- positionSurface(mBounds);
- draw(mBounds, Color.WHITE);
- // Update the history.
- mLastBounds.set(mBounds);
- }
- mSurfaceControl.show();
- } else {
- mSurfaceControl.hide();
- }
- }
-
- public void setBounds(TaskStack stack) {
- stack.getBounds(mBounds);
- if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
- }
-
- public void setLayer(int layer) {
- mSurfaceControl.setLayer(layer);
+ mLayer = layer;
+ mSurfaceControl.setLayer(mLayer);
}
}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index f79896b..7dd716e 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -291,12 +291,6 @@
return mSurfaceControl != null;
}
- static int deltaRotation(int oldRotation, int newRotation) {
- int delta = newRotation - oldRotation;
- if (delta < 0) delta += 4;
- return delta;
- }
-
private void setSnapshotTransformInTransaction(Matrix matrix, float alpha) {
if (mSurfaceControl != null) {
matrix.getValues(mTmpFloats);
@@ -352,7 +346,7 @@
// Compute the transformation matrix that must be applied
// to the snapshot to make it stay in the same original position
// with the current screen rotation.
- int delta = deltaRotation(rotation, Surface.ROTATION_0);
+ int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
if (DEBUG_STATE) Slog.v(TAG, "**** ROTATION: " + delta);
@@ -391,7 +385,7 @@
boolean firstStart = false;
// Figure out how the screen has moved from the original rotation.
- int delta = deltaRotation(mCurRotation, mOriginalRotation);
+ int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation);
if (TWO_PHASE_ANIMATION && mFinishExitAnimation == null
&& (!dismissing || delta != Surface.ROTATION_0)) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index d68c056..487483e9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -461,6 +461,16 @@
return mService.getWindowId(window);
}
+ @Override
+ public void pokeDrawLock(IBinder window) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mService.pokeDrawLock(this, window);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
void windowAddedLocked() {
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a9b26e2..b8f26c96 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -72,6 +72,19 @@
mService.mTaskIdToTask.delete(mTaskId);
}
+ void moveTaskToStack(TaskStack stack, boolean toTop) {
+ if (stack == mStack) {
+ return;
+ }
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
+ + " from stack=" + mStack);
+ EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
+ if (mStack != null) {
+ mStack.removeTask(this);
+ }
+ stack.addTask(this, toTop);
+ }
+
boolean removeAppToken(AppWindowToken wtoken) {
boolean removed = mAppTokens.remove(wtoken);
if (mAppTokens.size() == 0) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index c677e2c..3e1c5ff 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,6 +26,7 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.TypedValue;
+import android.view.Surface;
import com.android.server.EventLogTags;
@@ -52,6 +53,8 @@
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
+ /** For handling display rotations. */
+ private Rect mTmpRect2 = new Rect();
/** Content limits relative to the DisplayContent this sits in. */
private Rect mBounds = new Rect();
@@ -94,6 +97,9 @@
// the status bar.
boolean mUnderStatusBar;
+ // Device rotation as of the last time {@link #mBounds} was set.
+ int mRotation;
+
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
@@ -135,8 +141,10 @@
/** Set the stack bounds. Passing in null sets the bounds to fullscreen. */
boolean setBounds(Rect bounds) {
boolean oldFullscreen = mFullscreen;
+ int rotation = Surface.ROTATION_0;
if (mDisplayContent != null) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ rotation = mDisplayContent.getDisplayInfo().rotation;
if (bounds == null) {
bounds = mTmpRect;
mFullscreen = true;
@@ -147,10 +155,10 @@
}
if (bounds == null) {
- // Can set to fullscreen if we don't have a display to get bounds from...
+ // Can't set to fullscreen if we don't have a display to get bounds from...
return false;
}
- if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) {
+ if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
return false;
}
@@ -158,6 +166,7 @@
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
mUnderStatusBar = (mBounds.top == 0);
+ mRotation = rotation;
updateOverrideConfiguration();
return true;
}
@@ -191,9 +200,42 @@
}
void updateDisplayInfo() {
- if (mFullscreen && mDisplayContent != null) {
+ if (mFullscreen) {
+ setBounds(null);
+ } else if (mDisplayContent != null) {
+ final int newRotation = mDisplayContent.getDisplayInfo().rotation;
+ if (mRotation == newRotation) {
+ return;
+ }
+
+ // Device rotation changed. We don't want the stack to move around on the screen when
+ // this happens, so update the stack bounds so it stays in the same place.
+ final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation);
mDisplayContent.getLogicalDisplayRect(mTmpRect);
- setBounds(mTmpRect);
+ switch (rotationDelta) {
+ case Surface.ROTATION_0:
+ mTmpRect2.set(mBounds);
+ break;
+ case Surface.ROTATION_90:
+ mTmpRect2.top = mTmpRect.bottom - mBounds.right;
+ mTmpRect2.left = mBounds.top;
+ mTmpRect2.right = mTmpRect2.left + mBounds.height();
+ mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
+ break;
+ case Surface.ROTATION_180:
+ mTmpRect2.top = mTmpRect.bottom - mBounds.bottom;
+ mTmpRect2.left = mTmpRect.right - mBounds.right;
+ mTmpRect2.right = mTmpRect2.left + mBounds.width();
+ mTmpRect2.bottom = mTmpRect2.top + mBounds.height();
+ break;
+ case Surface.ROTATION_270:
+ mTmpRect2.top = mBounds.left;
+ mTmpRect2.left = mTmpRect.right - mBounds.bottom;
+ mTmpRect2.right = mTmpRect2.left + mBounds.height();
+ mTmpRect2.bottom = mTmpRect2.top + mBounds.width();
+ break;
+ }
+ setBounds(mTmpRect2);
}
}
@@ -328,7 +370,7 @@
for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
- mService.removeWindowInnerLocked(null, appWindows.get(winNdx));
+ mService.removeWindowInnerLocked(appWindows.get(winNdx));
doAnotherLayoutPass = true;
}
}
@@ -420,18 +462,24 @@
void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {
// Only set dim params on the highest dimmed layer.
- final WindowStateAnimator existingDimWinAnimator = mDimWinAnimator;
// Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
- if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null
- || !existingDimWinAnimator.mSurfaceShown
- || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
+ if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null
+ || !mDimWinAnimator.mSurfaceShown
+ || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
mDimWinAnimator = newWinAnimator;
+ if (mDimWinAnimator.mWin.mAppToken == null
+ && !mFullscreen && mDisplayContent != null) {
+ // Dim should cover the entire screen for system windows.
+ mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ mDimLayer.setBounds(mTmpRect);
+ }
}
}
void stopDimmingIfNeeded() {
if (!mDimmingTag && isDimming()) {
mDimWinAnimator = null;
+ mDimLayer.setBounds(mBounds);
}
}
@@ -446,7 +494,7 @@
}
}
- void switchUser(int userId) {
+ void switchUser() {
int top = mTasks.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mTasks.get(taskNdx);
@@ -475,7 +523,7 @@
}
if (mDimLayer.isDimming()) {
pw.print(prefix); pw.println("mDimLayer:");
- mDimLayer.printTo(prefix, pw);
+ mDimLayer.printTo(prefix + " ", pw);
pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
}
if (!mExitingAppTokens.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 0c5d06a..a11963c 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -62,8 +62,12 @@
final Context mContext;
final WindowManagerPolicy mPolicy;
+ /** Is any window animating? */
boolean mAnimating;
+ /** Is any app window animating? */
+ boolean mAppWindowAnimating;
+
final Choreographer.FrameCallback mAnimationFrameCallback;
/** Time of current animation step. Reset on each iteration */
@@ -146,35 +150,6 @@
mDisplayContentsAnimators.delete(displayId);
}
- void hideWallpapersLocked(final WindowState w) {
- final WindowState wallpaperTarget = mService.mWallpaperTarget;
- final WindowState lowerWallpaperTarget = mService.mLowerWallpaperTarget;
- final ArrayList<WindowToken> wallpaperTokens = mService.mWallpaperTokens;
-
- if ((wallpaperTarget == w && lowerWallpaperTarget == null) || wallpaperTarget == null) {
- final int numTokens = wallpaperTokens.size();
- for (int i = numTokens - 1; i >= 0; i--) {
- final WindowToken token = wallpaperTokens.get(i);
- final int numWindows = token.windows.size();
- for (int j = numWindows - 1; j >= 0; j--) {
- final WindowState wallpaper = token.windows.get(j);
- final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
- if (!winAnimator.mLastHidden) {
- winAnimator.hide();
- mService.dispatchWallpaperVisibility(wallpaper, false);
- setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
- WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
- }
- }
- if (WindowManagerService.DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG,
- "Hiding wallpaper " + token + " from " + w
- + " target=" + wallpaperTarget + " lower=" + lowerWallpaperTarget
- + "\n" + Debug.getCallers(5, " "));
- token.hidden = true;
- }
- }
- }
-
private void updateAppWindowsLocked(int displayId) {
ArrayList<TaskStack> stacks = mService.getDisplayContentLocked(displayId).getStacks();
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -187,7 +162,7 @@
final boolean wasAnimating = appAnimator.animation != null
&& appAnimator.animation != AppWindowAnimator.sDummyAnimation;
if (appAnimator.stepAnimationLocked(mCurrentTime)) {
- mAnimating = true;
+ mAnimating = mAppWindowAnimating = true;
} else if (wasAnimating) {
// stopped animating, do one more pass through the layout
setAppLayoutChanges(appAnimator,
@@ -206,7 +181,7 @@
final boolean wasAnimating = appAnimator.animation != null
&& appAnimator.animation != AppWindowAnimator.sDummyAnimation;
if (appAnimator.stepAnimationLocked(mCurrentTime)) {
- mAnimating = true;
+ mAnimating = mAppWindowAnimating = true;
} else if (wasAnimating) {
// stopped animating, do one more pass through the layout
setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER,
@@ -630,6 +605,7 @@
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
boolean wasAnimating = mAnimating;
mAnimating = false;
+ mAppWindowAnimating = false;
if (WindowManagerService.DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 71fddfb..7e69e87 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -64,11 +65,9 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -127,7 +126,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
@@ -136,7 +134,6 @@
import android.view.WindowManagerPolicy.PointerEventListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.view.animation.Transformation;
import java.io.BufferedWriter;
import java.io.DataInputStream;
@@ -181,7 +178,6 @@
static final boolean DEBUG_CONFIGURATION = false;
static final boolean DEBUG_APP_TRANSITIONS = false;
static final boolean DEBUG_STARTING_WINDOW = false;
- static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
static final boolean DEBUG_DRAG = false;
@@ -194,6 +190,7 @@
static final boolean DEBUG_TASK_MOVEMENT = false;
static final boolean DEBUG_STACK = false;
static final boolean DEBUG_DISPLAY = false;
+ static final boolean DEBUG_POWER = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -332,6 +329,7 @@
final boolean mHaveInputMethods;
final boolean mHasPermanentDpad;
+ final long mDrawLockTimeoutMillis;
final boolean mAllowBootMessages;
@@ -413,7 +411,7 @@
* This is set when we have run out of memory, and will either be an empty
* list or contain windows that need to be force removed.
*/
- ArrayList<WindowState> mForceRemoves;
+ final ArrayList<WindowState> mForceRemoves = new ArrayList<>();
/**
* Windows that clients are waiting to have drawn.
@@ -582,7 +580,7 @@
}
}
- final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
+ private final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
// If non-null, this is the currently visible window that is associated
// with the wallpaper.
@@ -685,11 +683,11 @@
final WindowAnimator mAnimator;
- SparseArray<Task> mTaskIdToTask = new SparseArray<Task>();
+ SparseArray<Task> mTaskIdToTask = new SparseArray<>();
/** All of the TaskStacks in the window manager, unordered. For an ordered list call
* DisplayContent.getStacks(). */
- SparseArray<TaskStack> mStackIdToStack = new SparseArray<TaskStack>();
+ SparseArray<TaskStack> mStackIdToStack = new SparseArray<>();
private final PointerEventDispatcher mPointerEventDispatcher;
@@ -784,6 +782,35 @@
// For example, when this flag is true, there will be no wallpaper service.
final boolean mOnlyCore;
+ /** Listener to notify activity manager about app transitions. */
+ private final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
+ = new WindowManagerInternal.AppTransitionListener() {
+
+ @Override
+ public void onAppTransitionFinishedLocked(IBinder token) {
+ AppWindowToken atoken = findAppWindowToken(token);
+ if (atoken == null) {
+ return;
+ }
+ if (atoken.mLaunchTaskBehind) {
+ try {
+ mActivityManager.notifyLaunchTaskBehindComplete(atoken.token);
+ } catch (RemoteException e) {
+ }
+ atoken.mLaunchTaskBehind = false;
+ } else {
+ atoken.updateReportedVisibilityLocked();
+ if (atoken.mEnteringAnimation) {
+ atoken.mEnteringAnimation = false;
+ try {
+ mActivityManager.notifyEnterAnimationComplete(atoken.token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+ };
+
public static WindowManagerService main(final Context context,
final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs,
@@ -822,6 +849,8 @@
com.android.internal.R.bool.config_hasPermanentDpad);
mInTouchMode = context.getResources().getBoolean(
com.android.internal.R.bool.config_defaultInTouchMode);
+ mDrawLockTimeoutMillis = context.getResources().getInteger(
+ com.android.internal.R.integer.config_drawLockTimeoutMillis);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplaySettings = new DisplaySettings();
@@ -860,6 +889,7 @@
mScreenFrozenLock.setReferenceCounted(false);
mAppTransition = new AppTransition(context, mH);
+ mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
mActivityManager = ActivityManagerNative.getDefault();
mBatteryStats = BatteryStatsService.getService();
@@ -1694,7 +1724,7 @@
return true;
}
- final boolean isWallpaperVisible(WindowState wallpaperTarget) {
+ private boolean isWallpaperVisible(WindowState wallpaperTarget) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
@@ -1708,10 +1738,35 @@
|| mLowerWallpaperTarget != null;
}
- static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
- static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
+ void hideWallpapersLocked(final WindowState winGoingAway) {
+ if (mWallpaperTarget != null &&
+ (mWallpaperTarget != winGoingAway || mLowerWallpaperTarget != null)) {
+ return;
+ }
- int adjustWallpaperWindowsLocked() {
+ for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
+ final WindowToken token = mWallpaperTokens.get(i);
+ for (int j = token.windows.size() - 1; j >= 0; j--) {
+ final WindowState wallpaper = token.windows.get(j);
+ final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
+ if (!winAnimator.mLastHidden) {
+ winAnimator.hide();
+ dispatchWallpaperVisibility(wallpaper, false);
+ final DisplayContent displayContent = wallpaper.getDisplayContent();
+ if (displayContent != null) {
+ displayContent.pendingLayoutChanges |=
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+ }
+ }
+ }
+ if (DEBUG_WALLPAPER_LIGHT && !token.hidden) Slog.d(TAG, "Hiding wallpaper " + token
+ + " from " + winGoingAway + " target=" + mWallpaperTarget + " lower="
+ + mLowerWallpaperTarget + "\n" + Debug.getCallers(5, " "));
+ token.hidden = true;
+ }
+ }
+
+ boolean adjustWallpaperWindowsLocked() {
mInnerFields.mWallpaperMayChange = false;
boolean targetChanged = false;
@@ -1890,7 +1945,7 @@
// AND any starting window associated with it, AND below the
// maximum layer the policy allows for wallpapers.
while (foundI > 0) {
- WindowState wb = windows.get(foundI-1);
+ WindowState wb = windows.get(foundI - 1);
if (wb.mBaseLayer < maxLayer &&
wb.mAttachedWindow != foundW &&
(foundW.mAttachedWindow == null ||
@@ -1916,7 +1971,7 @@
} else {
// Okay i is the position immediately above the wallpaper. Look at
// what is below it for later.
- foundW = foundI > 0 ? windows.get(foundI-1) : null;
+ foundW = foundI > 0 ? windows.get(foundI - 1) : null;
}
if (visible) {
@@ -1938,44 +1993,37 @@
// Start stepping backwards from here, ensuring that our wallpaper windows
// are correctly placed.
- int changed = 0;
- int curTokenIndex = mWallpaperTokens.size();
- while (curTokenIndex > 0) {
- curTokenIndex--;
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ boolean changed = false;
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowToken token = mWallpaperTokens.get(curTokenNdx);
if (token.hidden == visible) {
if (DEBUG_WALLPAPER_LIGHT) Slog.d(TAG,
"Wallpaper token " + token + " hidden=" + !visible);
- changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
token.hidden = !visible;
- // Need to do a layout to ensure the wallpaper now has the
- // correct size.
+ // Need to do a layout to ensure the wallpaper now has the correct size.
getDefaultDisplayContentLocked().layoutNeeded = true;
}
- int curWallpaperIndex = token.windows.size();
- while (curWallpaperIndex > 0) {
- curWallpaperIndex--;
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ final WindowList tokenWindows = token.windows;
+ for (int wallpaperNdx = tokenWindows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = tokenWindows.get(wallpaperNdx);
if (visible) {
updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
}
- // First, make sure the client has the current visibility
- // state.
+ // First, make sure the client has the current visibility state.
dispatchWallpaperVisibility(wallpaper, visible);
- wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
+ wallpaper.mWinAnimator.mAnimLayer =
+ wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
if (DEBUG_LAYERS || DEBUG_WALLPAPER_LIGHT) Slog.v(TAG, "adjustWallpaper win "
+ wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
- // First, if this window is at the current index, then all
- // is well.
+ // First, if this window is at the current index, then all is well.
if (wallpaper == foundW) {
foundI--;
- foundW = foundI > 0
- ? windows.get(foundI-1) : null;
+ foundW = foundI > 0 ? windows.get(foundI - 1) : null;
continue;
}
@@ -2011,52 +2059,24 @@
windows.add(insertionIndex, wallpaper);
mWindowsChanged = true;
- changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
+ changed = true;
}
}
- /*
- final TaskStack targetStack =
- mWallpaperTarget == null ? null : mWallpaperTarget.getStack();
- if ((changed & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0 &&
- targetStack != null && !targetStack.isHomeStack()) {
- // If the wallpaper target is not on the home stack then make sure that all windows
- // from other non-home stacks are above the wallpaper.
- for (i = foundI - 1; i >= 0; --i) {
- WindowState win = windows.get(i);
- if (!win.isVisibleLw()) {
- continue;
- }
- final TaskStack winStack = win.getStack();
- if (winStack != null && !winStack.isHomeStack() && winStack != targetStack) {
- windows.remove(i);
- windows.add(foundI + 1, win);
- }
- }
- }
- */
-
- if (targetChanged && DEBUG_WALLPAPER_LIGHT) {
- Slog.d(TAG, "New wallpaper: target=" + mWallpaperTarget
- + " lower=" + mLowerWallpaperTarget + " upper="
- + mUpperWallpaperTarget);
- }
+ if (targetChanged && DEBUG_WALLPAPER_LIGHT) Slog.d(TAG, "New wallpaper: target="
+ + mWallpaperTarget + " lower=" + mLowerWallpaperTarget + " upper="
+ + mUpperWallpaperTarget);
return changed;
}
void setWallpaperAnimLayerAdjustmentLocked(int adj) {
- if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
- "Setting wallpaper layer adj to " + adj);
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Setting wallpaper layer adj to " + adj);
mWallpaperAnimLayerAdjustment = adj;
- int curTokenIndex = mWallpaperTokens.size();
- while (curTokenIndex > 0) {
- curTokenIndex--;
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
- int curWallpaperIndex = token.windows.size();
- while (curWallpaperIndex > 0) {
- curWallpaperIndex--;
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
wallpaper.mWinAnimator.mAnimLayer = wallpaper.mLayer + adj;
if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "setWallpaper win "
+ wallpaper + " anim layer: " + wallpaper.mWinAnimator.mAnimLayer);
@@ -2190,14 +2210,10 @@
}
}
- int curTokenIndex = mWallpaperTokens.size();
- while (curTokenIndex > 0) {
- curTokenIndex--;
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
- int curWallpaperIndex = token.windows.size();
- while (curWallpaperIndex > 0) {
- curWallpaperIndex--;
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
winAnimator.computeShownFrameLocked();
@@ -2229,7 +2245,7 @@
}
}
- void updateWallpaperVisibilityLocked() {
+ private void updateWallpaperVisibilityLocked() {
final boolean visible = isWallpaperVisible(mWallpaperTarget);
final DisplayContent displayContent = mWallpaperTarget.getDisplayContent();
if (displayContent == null) {
@@ -2239,21 +2255,18 @@
final int dw = displayInfo.logicalWidth;
final int dh = displayInfo.logicalHeight;
- int curTokenIndex = mWallpaperTokens.size();
- while (curTokenIndex > 0) {
- curTokenIndex--;
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ WindowToken token = mWallpaperTokens.get(curTokenNdx);
if (token.hidden == visible) {
token.hidden = !visible;
// Need to do a layout to ensure the wallpaper now has the
// correct size.
- getDefaultDisplayContentLocked().layoutNeeded = true;
+ displayContent.layoutNeeded = true;
}
- int curWallpaperIndex = token.windows.size();
- while (curWallpaperIndex > 0) {
- curWallpaperIndex--;
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ final WindowList windows = token.windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
if (visible) {
updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
}
@@ -2667,7 +2680,7 @@
}
}
- removeWindowInnerLocked(session, win);
+ removeWindowInnerLocked(win);
// Removing a visible window will effect the computed orientation
// So just update orientation if needed.
if (wasVisible && updateOrientationFromAppTokensLocked(false)) {
@@ -2677,7 +2690,7 @@
Binder.restoreCallingIdentity(origId);
}
- void removeWindowInnerLocked(Session session, WindowState win) {
+ void removeWindowInnerLocked(WindowState win) {
if (win.mRemoved) {
// Nothing to do.
return;
@@ -2687,7 +2700,7 @@
WindowState cwin = win.mChildWindows.get(i);
Slog.w(TAG, "Force-removing child win " + cwin + " from container "
+ win);
- removeWindowInnerLocked(cwin.mSession, cwin);
+ removeWindowInnerLocked(cwin);
}
win.mRemoved = true;
@@ -2911,14 +2924,10 @@
if (window == mWallpaperTarget || window == mLowerWallpaperTarget
|| window == mUpperWallpaperTarget) {
boolean doWait = sync;
- int curTokenIndex = mWallpaperTokens.size();
- while (curTokenIndex > 0) {
- curTokenIndex--;
- WindowToken token = mWallpaperTokens.get(curTokenIndex);
- int curWallpaperIndex = token.windows.size();
- while (curWallpaperIndex > 0) {
- curWallpaperIndex--;
- WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ final WindowList windows = mWallpaperTokens.get(curTokenNdx).windows;
+ for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+ WindowState wallpaper = windows.get(wallpaperNdx);
try {
wallpaper.mClient.dispatchWallpaperCommand(action,
x, y, z, extras, sync);
@@ -2956,6 +2965,15 @@
}
}
+ public void pokeDrawLock(Session session, IBinder token) {
+ synchronized (mWindowMap) {
+ WindowState window = windowForClientLocked(session, token, false);
+ if (window != null) {
+ window.pokeDrawLockLw(mDrawLockTimeoutMillis);
+ }
+ }
+ }
+
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
@@ -3556,13 +3574,13 @@
false /*updateInputWindows*/);
}
- if (delayed) {
- if (displayContent != null) {
- displayContent.mExitingTokens.add(wtoken);
- }
+ if (delayed && displayContent != null) {
+ displayContent.mExitingTokens.add(wtoken);
} else if (wtoken.windowType == TYPE_WALLPAPER) {
mWallpaperTokens.remove(wtoken);
}
+ } else if (wtoken.windowType == TYPE_WALLPAPER) {
+ mWallpaperTokens.remove(wtoken);
}
mInputMonitor.updateInputWindowsLw(true /*force*/);
@@ -3680,14 +3698,12 @@
// TODO(multidisplay): Change to the correct display.
final WindowList windows = getDefaultWindowListLocked();
- int pos = windows.size() - 1;
- while (pos >= 0) {
+ for (int pos = windows.size() - 1; pos >= 0; --pos) {
WindowState win = windows.get(pos);
- pos--;
if (win.mAppToken != null) {
// We hit an application window. so the orientation will be determined by the
// app window. No point in continuing further.
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ return (mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
continue;
@@ -3699,9 +3715,9 @@
}
if (DEBUG_ORIENTATION) Slog.v(TAG, win + " forcing orientation to " + req);
- return (mLastWindowForcedOrientation=req);
+ return (mLastWindowForcedOrientation = req);
}
- return (mLastWindowForcedOrientation=ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ return (mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
public int getOrientationFromAppTokensLocked() {
@@ -3759,14 +3775,12 @@
// to use the orientation behind it, then just take whatever
// orientation it has and ignores whatever is under it.
lastFullscreen = atoken.appFullscreen;
- if (lastFullscreen
- && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ if (lastFullscreen && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
+ " -- full screen, return " + or);
return or;
}
- // If this application has requested an explicit orientation,
- // then use it.
+ // If this application has requested an explicit orientation, then use it.
if (or != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
&& or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
if (DEBUG_ORIENTATION) Slog.v(TAG, "Done at " + atoken
@@ -3802,6 +3816,9 @@
private Configuration updateOrientationFromAppTokensLocked(
Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
+ if (!mDisplayReady) {
+ return null;
+ }
Configuration config = null;
if (updateOrientationFromAppTokensLocked(false)) {
@@ -3820,20 +3837,19 @@
// the value of the previous configuration.
mTempConfiguration.setToDefaults();
mTempConfiguration.fontScale = currentConfig.fontScale;
- if (computeScreenConfigurationLocked(mTempConfiguration)) {
- if (currentConfig.diff(mTempConfiguration) != 0) {
- mWaitingForConfig = true;
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- displayContent.layoutNeeded = true;
- int anim[] = new int[2];
- if (displayContent.isDimming()) {
- anim[0] = anim[1] = 0;
- } else {
- mPolicy.selectRotationAnimationLw(anim);
- }
- startFreezingDisplayLocked(false, anim[0], anim[1]);
- config = new Configuration(mTempConfiguration);
+ computeScreenConfigurationLocked(mTempConfiguration);
+ if (currentConfig.diff(mTempConfiguration) != 0) {
+ mWaitingForConfig = true;
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ displayContent.layoutNeeded = true;
+ int anim[] = new int[2];
+ if (displayContent.isDimming()) {
+ anim[0] = anim[1] = 0;
+ } else {
+ mPolicy.selectRotationAnimationLw(anim);
}
+ startFreezingDisplayLocked(false, anim[0], anim[1]);
+ config = new Configuration(mTempConfiguration);
}
}
@@ -3957,20 +3973,7 @@
} else {
stack = null;
}
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedStackFrame");
- SurfaceControl.openTransaction();
- try {
- if (stack == null) {
- mFocusedStackFrame.setVisibility(false);
- } else {
- mFocusedStackFrame.setBounds(stack);
- final boolean multipleStacks = !stack.isFullscreen();
- mFocusedStackFrame.setVisibility(multipleStacks);
- }
- } finally {
- SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedStackFrame");
- }
+ mFocusedStackFrame.setVisibility(stack);
}
@Override
@@ -4079,6 +4082,15 @@
}
@Override
+ public void overridePendingAppTransitionClipReveal(int startX, int startY,
+ int startWidth, int startHeight) {
+ synchronized(mWindowMap) {
+ mAppTransition.overridePendingAppTransitionClipReveal(startX, startY, startWidth,
+ startHeight);
+ }
+ }
+
+ @Override
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
int startY, IRemoteCallback startedCallback, boolean scaleUp) {
synchronized(mWindowMap) {
@@ -4304,8 +4316,13 @@
+ " ShowWallpaper="
+ ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowShowWallpaper, false));
- if (ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
+ final boolean windowIsTranslucentDefined = ent.array.hasValue(
+ com.android.internal.R.styleable.Window_windowIsTranslucent);
+ final boolean windowIsTranslucent = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+ final boolean windowSwipeToDismiss = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);
+ if (windowIsTranslucent || (!windowIsTranslucentDefined && windowSwipeToDismiss)) {
return;
}
if (ent.array.getBoolean(
@@ -4614,6 +4631,7 @@
}
final long origId = Binder.clearCallingIdentity();
+ wtoken.inPendingTransaction = false;
setTokenVisibilityLocked(wtoken, null, visible, AppTransition.TRANSIT_UNSET,
true, wtoken.voiceInteraction);
wtoken.updateReportedVisibilityLocked();
@@ -5076,6 +5094,7 @@
+ " to " + (toTop ? "top" : "bottom"));
Task task = mTaskIdToTask.get(taskId);
if (task == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "addTask: could not find taskId=" + taskId);
return;
}
TaskStack stack = mStackIdToStack.get(stackId);
@@ -5086,6 +5105,27 @@
}
}
+ public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+ synchronized (mWindowMap) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: moving taskId=" + taskId
+ + " to stackId=" + stackId + " at " + (toTop ? "top" : "bottom"));
+ Task task = mTaskIdToTask.get(taskId);
+ if (task == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find taskId=" + taskId);
+ return;
+ }
+ TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: could not find stackId=" + stackId);
+ return;
+ }
+ task.moveTaskToStack(stack, toTop);
+ final DisplayContent displayContent = stack.getDisplayContent();
+ displayContent.layoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ }
+
/**
* Re-sizes the specified stack and its containing windows.
* Returns a {@link Configuration} object that contains configurations settings
@@ -5116,6 +5156,24 @@
bounds.setEmpty();
}
+ /** Returns the id of an application (non-home stack) stack that match the input bounds.
+ * -1 if no stack matches.*/
+ public int getStackIdWithBounds(Rect bounds) {
+ Rect stackBounds = new Rect();
+ synchronized (mWindowMap) {
+ for (int i = mStackIdToStack.size() - 1; i >= 0; --i) {
+ TaskStack stack = mStackIdToStack.valueAt(i);
+ if (stack.mStackId != HOME_STACK_ID) {
+ stack.getBounds(stackBounds);
+ if (stackBounds.equals(bounds)) {
+ return stack.mStackId;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
/** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
* Returns a {@link Configuration} object that contains configurations settings
* that should be overridden due to the operation.
@@ -5496,7 +5554,7 @@
final int numDisplays = mDisplayContents.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
- displayContent.switchUserStacks(newUserId);
+ displayContent.switchUserStacks();
rebuildAppWindowListLocked(displayContent);
}
performLayoutAndPlaceSurfacesLocked();
@@ -6374,13 +6432,12 @@
screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
- // We need to update our screen size information to match the new
- // rotation. Note that this is redundant with the later call to
- // sendNewConfiguration() that must be called after this function
- // returns... however we need to do the screen size part of that
- // before then so we have the correct size to use when initializing
- // the rotation animation for the new rotation.
- computeScreenConfigurationLocked(null);
+ // We need to update our screen size information to match the new rotation. If the rotation
+ // has actually changed then this method will return true and, according to the comment at
+ // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
+ // By updating the Display info here it will be available to
+ // computeScreenConfigurationLocked later.
+ updateDisplayAndOrientationLocked();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!inTransaction) {
@@ -6929,9 +6986,11 @@
public Configuration computeNewConfiguration() {
synchronized (mWindowMap) {
+ if (!mDisplayReady) {
+ return null;
+ }
Configuration config = computeNewConfigurationLocked();
- if (config == null && mWaitingForConfig) {
- // Nothing changed but we are waiting for something... stop that!
+ if (mWaitingForConfig) {
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
performLayoutAndPlaceSurfacesLocked();
@@ -6943,9 +7002,7 @@
Configuration computeNewConfigurationLocked() {
Configuration config = new Configuration();
config.fontScale = 0;
- if (!computeScreenConfigurationLocked(config)) {
- return null;
- }
+ computeScreenConfigurationLocked(config);
return config;
}
@@ -7052,11 +7109,8 @@
return sw;
}
- private boolean computeScreenConfigurationLocked(Configuration config) {
- if (!mDisplayReady) {
- return false;
- }
-
+ /** Do not call if mDisplayReady == false */
+ DisplayInfo updateDisplayAndOrientationLocked() {
// TODO(multidisplay): For now, apply Configuration to main screen only.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
@@ -7086,11 +7140,6 @@
}
}
- if (config != null) {
- config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
- Configuration.ORIENTATION_LANDSCAPE;
- }
-
// Update application display metrics.
final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
@@ -7113,89 +7162,98 @@
Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
}
- final DisplayMetrics dm = mDisplayMetrics;
- mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
+ mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(mDisplayMetrics,
mCompatDisplayMetrics);
+ return displayInfo;
+ }
- if (config != null) {
- config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
- / dm.density);
- config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
- / dm.density);
- computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, dm.density, config);
+ /** Do not call if mDisplayReady == false */
+ void computeScreenConfigurationLocked(Configuration config) {
+ final DisplayInfo displayInfo = updateDisplayAndOrientationLocked();
- config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
- config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
- config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
- config.densityDpi = displayContent.mBaseDisplayDensity;
+ final int dw = displayInfo.logicalWidth;
+ final int dh = displayInfo.logicalHeight;
+ config.orientation = (dw <= dh) ? Configuration.ORIENTATION_PORTRAIT :
+ Configuration.ORIENTATION_LANDSCAPE;
+ config.screenWidthDp =
+ (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation) / mDisplayMetrics.density);
+ config.screenHeightDp =
+ (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation) / mDisplayMetrics.density);
+ final boolean rotated = (mRotation == Surface.ROTATION_90
+ || mRotation == Surface.ROTATION_270);
+ computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, mDisplayMetrics.density,
+ config);
- // Update the configuration based on available input devices, lid switch,
- // and platform configuration.
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- config.navigation = Configuration.NAVIGATION_NONAV;
+ config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
+ config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
+ config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated,
+ mDisplayMetrics, dw, dh);
+ config.densityDpi = displayInfo.logicalDensityDpi;
- int keyboardPresence = 0;
- int navigationPresence = 0;
- final InputDevice[] devices = mInputManager.getInputDevices();
- final int len = devices.length;
- for (int i = 0; i < len; i++) {
- InputDevice device = devices[i];
- if (!device.isVirtual()) {
- final int sources = device.getSources();
- final int presenceFlag = device.isExternal() ?
- WindowManagerPolicy.PRESENCE_EXTERNAL :
- WindowManagerPolicy.PRESENCE_INTERNAL;
+ // Update the configuration based on available input devices, lid switch,
+ // and platform configuration.
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ config.navigation = Configuration.NAVIGATION_NONAV;
- if (mIsTouchDevice) {
- if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
- InputDevice.SOURCE_TOUCHSCREEN) {
- config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
- }
- } else {
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ int keyboardPresence = 0;
+ int navigationPresence = 0;
+ final InputDevice[] devices = mInputManager.getInputDevices();
+ final int len = devices.length;
+ for (int i = 0; i < len; i++) {
+ InputDevice device = devices[i];
+ if (!device.isVirtual()) {
+ final int sources = device.getSources();
+ final int presenceFlag = device.isExternal() ?
+ WindowManagerPolicy.PRESENCE_EXTERNAL :
+ WindowManagerPolicy.PRESENCE_INTERNAL;
+
+ if (mIsTouchDevice) {
+ if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
+ InputDevice.SOURCE_TOUCHSCREEN) {
+ config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
}
+ } else {
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ }
- if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
- config.navigation = Configuration.NAVIGATION_TRACKBALL;
- navigationPresence |= presenceFlag;
- } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
- && config.navigation == Configuration.NAVIGATION_NONAV) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= presenceFlag;
- }
+ if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+ config.navigation = Configuration.NAVIGATION_TRACKBALL;
+ navigationPresence |= presenceFlag;
+ } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
+ && config.navigation == Configuration.NAVIGATION_NONAV) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= presenceFlag;
+ }
- if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
- config.keyboard = Configuration.KEYBOARD_QWERTY;
- keyboardPresence |= presenceFlag;
- }
+ if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+ config.keyboard = Configuration.KEYBOARD_QWERTY;
+ keyboardPresence |= presenceFlag;
}
}
-
- if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
- config.navigation = Configuration.NAVIGATION_DPAD;
- navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
- }
-
- // Determine whether a hard keyboard is available and enabled.
- boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
- if (hardKeyboardAvailable != mHardKeyboardAvailable) {
- mHardKeyboardAvailable = hardKeyboardAvailable;
- mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- }
- if (mShowImeWithHardKeyboard) {
- config.keyboard = Configuration.KEYBOARD_NOKEYS;
- }
-
- // Let the policy update hidden states.
- config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
- config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
- config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
- mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
- return true;
+ if (config.navigation == Configuration.NAVIGATION_NONAV && mHasPermanentDpad) {
+ config.navigation = Configuration.NAVIGATION_DPAD;
+ navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
+ }
+
+ // Determine whether a hard keyboard is available and enabled.
+ boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
+ if (hardKeyboardAvailable != mHardKeyboardAvailable) {
+ mHardKeyboardAvailable = hardKeyboardAvailable;
+ mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ }
+ if (mShowImeWithHardKeyboard) {
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ }
+
+ // Let the policy update hidden states.
+ config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
+ config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
+ config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
+ mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
public boolean isHardKeyboardAvailable() {
@@ -7935,16 +7993,16 @@
break;
case TAP_OUTSIDE_STACK: {
-// int stackId;
-// synchronized (mWindowMap) {
-// stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
-// }
-// if (stackId >= 0) {
-// try {
-// mActivityManager.setFocusedStack(stackId);
-// } catch (RemoteException e) {
-// }
-// }
+ int stackId;
+ synchronized (mWindowMap) {
+ stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
+ }
+ if (stackId >= 0) {
+ try {
+ mActivityManager.setFocusedStack(stackId);
+ } catch (RemoteException e) {
+ }
+ }
}
break;
case NOTIFY_ACTIVITY_DRAWN:
@@ -8324,17 +8382,17 @@
// displayContent must not be null
private void reconfigureDisplayLocked(DisplayContent displayContent) {
// TODO: Multidisplay: for now only use with default display.
+ if (!mDisplayReady) {
+ return;
+ }
configureDisplayPolicyLocked(displayContent);
displayContent.layoutNeeded = true;
boolean configChanged = updateOrientationFromAppTokensLocked(false);
mTempConfiguration.setToDefaults();
mTempConfiguration.fontScale = mCurConfiguration.fontScale;
- if (computeScreenConfigurationLocked(mTempConfiguration)) {
- if (mCurConfiguration.diff(mTempConfiguration) != 0) {
- configChanged = true;
- }
- }
+ computeScreenConfigurationLocked(mTempConfiguration);
+ configChanged |= mCurConfiguration.diff(mTempConfiguration) != 0;
if (configChanged) {
mWaitingForConfig = true;
@@ -8635,29 +8693,24 @@
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmLayout");
mInLayout = true;
- boolean recoveringMemory = false;
- try {
- if (mForceRemoves != null) {
- recoveringMemory = true;
- // Wait a little bit for things to settle down, and off we go.
- for (int i=0; i<mForceRemoves.size(); i++) {
- WindowState ws = mForceRemoves.get(i);
- Slog.i(TAG, "Force removing: " + ws);
- removeWindowInnerLocked(ws.mSession, ws);
- }
- mForceRemoves = null;
- Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
- Object tmp = new Object();
- synchronized (tmp) {
- try {
- tmp.wait(250);
- } catch (InterruptedException e) {
- }
+ boolean recoveringMemory = false;
+ if (!mForceRemoves.isEmpty()) {
+ recoveringMemory = true;
+ // Wait a little bit for things to settle down, and off we go.
+ while (!mForceRemoves.isEmpty()) {
+ WindowState ws = mForceRemoves.remove(0);
+ Slog.i(TAG, "Force removing: " + ws);
+ removeWindowInnerLocked(ws);
+ }
+ Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
+ Object tmp = new Object();
+ synchronized (tmp) {
+ try {
+ tmp.wait(250);
+ } catch (InterruptedException e) {
}
}
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Unhandled exception while force removing for memory", e);
}
try {
@@ -8909,7 +8962,6 @@
if (mSkipAppTransitionAnimation) {
transit = AppTransition.TRANSIT_UNSET;
}
- mAppTransition.goodToGo();
mStartingIconInTransition = false;
mSkipAppTransitionAnimation = false;
@@ -9062,6 +9114,7 @@
for (int j = 0; j < N; j++) {
appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
}
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
}
}
@@ -9084,6 +9137,7 @@
appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
}
mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
if (animLp != null) {
int layer = -1;
@@ -9120,6 +9174,7 @@
if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
scheduleRemoveStartingWindowLocked(wtoken);
}
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
if (animLp != null) {
int layer = -1;
@@ -9204,6 +9259,7 @@
}
}
+ mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
mAppTransition.postAnimationCallback();
mAppTransition.clear();
@@ -9333,14 +9389,12 @@
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
- *
- * @param w WindowState this method is applied to.
- * @param currentTime The time which animations use for calculating transitions.
+ * @param w WindowState this method is applied to.
* @param innerDw Width of app window.
* @param innerDh Height of app window.
*/
- private void handleNotObscuredLocked(final WindowState w, final long currentTime,
- final int innerDw, final int innerDh) {
+ private void handleNotObscuredLocked(final WindowState w,
+ final int innerDw, final int innerDh) {
final WindowManager.LayoutParams attrs = w.mAttrs;
final int attrFlags = attrs.flags;
final boolean canBeSeen = w.isDisplayedLw();
@@ -9459,8 +9513,6 @@
+ Debug.getCallers(3));
}
- final long currentTime = SystemClock.uptimeMillis();
-
int i;
boolean updateInputWindowsNeeded = false;
@@ -9551,8 +9603,7 @@
if ((displayContent.pendingLayoutChanges &
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0 &&
- (adjustWallpaperWindowsLocked() &
- ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
+ adjustWallpaperWindowsLocked()) {
assignLayersLocked(windows);
displayContent.layoutNeeded = true;
}
@@ -9583,9 +9634,6 @@
// it is animating.
displayContent.pendingLayoutChanges = 0;
- if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number "
- + mLayoutRepeatCount, displayContent.pendingLayoutChanges);
-
if (isDefaultDisplay) {
mPolicy.beginPostLayoutPolicyLw(dw, dh);
for (i = windows.size() - 1; i >= 0; i--) {
@@ -9620,7 +9668,7 @@
// Update effect.
w.mObscured = mInnerFields.mObscured;
if (!mInnerFields.mObscured) {
- handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
+ handleNotObscuredLocked(w, innerDw, innerDh);
}
if (stack != null && !stack.testDimmingTag()) {
@@ -9669,7 +9717,7 @@
if (w.mHasSurface && !w.isHiddenFromUserLocked()) {
// Take care of the window being ready to display.
final boolean committed =
- winAnimator.commitFinishDrawingLocked(currentTime);
+ winAnimator.commitFinishDrawingLocked();
if (isDefaultDisplay && committed) {
if (w.mAttrs.type == TYPE_DREAM) {
// HACK: When a dream is shown, it may at that
@@ -9794,7 +9842,7 @@
defaultDisplay.pendingLayoutChanges);
}
- if (!mAnimator.mAnimating && mAppTransition.isRunning()) {
+ if (!mAnimator.mAppWindowAnimating && mAppTransition.isRunning()) {
// We have finished the animation of an app transition. To do
// this, we have delayed a lot of operations like showing and
// hiding apps, moving apps in Z-order, etc. The app token list
@@ -9968,7 +10016,9 @@
if (mAllowTheaterModeWakeFromLayout
|| Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 0) {
- if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
+ if (DEBUG_VISIBILITY || DEBUG_POWER) {
+ Slog.v(TAG, "Turning screen on after layout!");
+ }
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
mTurnOnScreen = false;
@@ -9999,7 +10049,7 @@
DisplayContentList displayList = new DisplayContentList();
for (i = 0; i < N; i++) {
WindowState w = mPendingRemoveTmp[i];
- removeWindowInnerLocked(w.mSession, w);
+ removeWindowInnerLocked(w);
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null && !displayList.contains(displayContent)) {
displayList.add(displayContent);
@@ -10175,10 +10225,6 @@
EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, winAnimator.mWin.toString(),
winAnimator.mSession.mPid, operation);
- if (mForceRemoves == null) {
- mForceRemoves = new ArrayList<WindowState>();
- }
-
long callingIdentity = Binder.clearCallingIdentity();
try {
// There was some problem... first, do a sanity check of the
@@ -10360,6 +10406,10 @@
+ ", flags=" + win.mAttrs.flags
+ ", canReceive=" + win.canReceiveKeys());
+ if (!win.canReceiveKeys()) {
+ continue;
+ }
+
AppWindowToken wtoken = win.mAppToken;
// If this window's application has been removed, just skip it.
@@ -10369,10 +10419,6 @@
continue;
}
- if (!win.canReceiveKeys()) {
- continue;
- }
-
// Descend through all of the app tokens and find the first that either matches
// win.mAppToken (return win) or mFocusedApp (return null).
if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING &&
@@ -10799,7 +10845,7 @@
void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
- if (mTokenMap.size() > 0) {
+ if (!mTokenMap.isEmpty()) {
pw.println(" All tokens:");
Iterator<WindowToken> it = mTokenMap.values().iterator();
while (it.hasNext()) {
@@ -10813,7 +10859,7 @@
}
}
}
- if (mWallpaperTokens.size() > 0) {
+ if (!mWallpaperTokens.isEmpty()) {
pw.println();
pw.println(" Wallpaper tokens:");
for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
@@ -10828,7 +10874,7 @@
}
}
}
- if (mFinishedStarting.size() > 0) {
+ if (!mFinishedStarting.isEmpty()) {
pw.println();
pw.println(" Finishing start of application tokens:");
for (int i=mFinishedStarting.size()-1; i>=0; i--) {
@@ -10843,7 +10889,7 @@
}
}
}
- if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
+ if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) {
pw.println();
if (mOpeningApps.size() > 0) {
pw.print(" mOpeningApps="); pw.println(mOpeningApps);
@@ -11078,7 +11124,7 @@
pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
pw.println(" mLayoutToAnim:");
- mAppTransition.dump(pw);
+ mAppTransition.dump(pw, " ");
}
}
@@ -11634,5 +11680,12 @@
WindowManagerService.this.removeWindowToken(token);
}
}
+
+ @Override
+ public void registerAppTransitionListener(AppTransitionListener listener) {
+ synchronized (mWindowMap) {
+ mAppTransition.registerListenerLocked(listener);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e88dace..04aea84 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -19,9 +19,9 @@
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
-
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
@@ -34,12 +34,15 @@
import android.app.AppOpsManager;
import android.os.Debug;
+import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.SystemClock;
+import android.os.WorkSource;
import android.util.TimeUtils;
import android.view.Display;
import android.view.IWindowFocusObserver;
import android.view.IWindowId;
+
import com.android.server.input.InputWindowHandle;
import android.content.Context;
@@ -343,6 +346,15 @@
/** When true this window can be displayed on screens owther than mOwnerUid's */
private boolean mShowToOwnerOnly;
+ /**
+ * Wake lock for drawing.
+ * Even though it's slightly more expensive to do so, we will use a separate wake lock
+ * for each app that is requesting to draw while dozing so that we can accurately track
+ * who is preventing the system from suspending.
+ * This lock is only acquired on first use.
+ */
+ PowerManager.WakeLock mDrawLock;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -1269,6 +1281,33 @@
}
}
+ public void pokeDrawLockLw(long timeout) {
+ if (isVisibleOrAdding()) {
+ if (mDrawLock == null) {
+ // We want the tag name to be somewhat stable so that it is easier to correlate
+ // in wake lock statistics. So in particular, we don't want to include the
+ // window's hash code as in toString().
+ CharSequence tag = mAttrs.getTitle();
+ if (tag == null) {
+ tag = mAttrs.packageName;
+ }
+ mDrawLock = mService.mPowerManager.newWakeLock(
+ PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
+ mDrawLock.setReferenceCounted(false);
+ mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
+ }
+ // Each call to acquire resets the timeout.
+ if (DEBUG_POWER) {
+ Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by "
+ + mAttrs.packageName);
+ }
+ mDrawLock.acquire(timeout);
+ } else if (DEBUG_POWER) {
+ Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window "
+ + "owned by " + mAttrs.packageName);
+ }
+ }
+
@Override
public boolean isAlive() {
return mClient.asBinder().isBinderAlive();
@@ -1288,6 +1327,15 @@
return displayContent.isDefaultDisplay;
}
+ @Override
+ public boolean isDimming() {
+ TaskStack stack = getStack();
+ if (stack == null) {
+ return false;
+ }
+ return stack.isDimming(mWinAnimator);
+ }
+
public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
mShowToOwnerOnly = showToOwnerOnly;
}
@@ -1551,6 +1599,9 @@
pw.print(prefix); pw.print("touchable region="); pw.println(region);
}
pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
+ if (mOverrideConfig != Configuration.EMPTY) {
+ pw.print(prefix); pw.print("mOverrideConfig="); pw.println(mOverrideConfig);
+ }
}
pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
pw.print(" mShownFrame="); mShownFrame.printShortString(pw);
@@ -1630,6 +1681,9 @@
pw.print(" mWallpaperDisplayOffsetY=");
pw.println(mWallpaperDisplayOffsetY);
}
+ if (mDrawLock != null) {
+ pw.println("mDrawLock=" + mDrawLock);
+ }
}
String makeInputChannelName() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8c79cf0..89ed5b7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -53,21 +53,16 @@
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
-import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
-import com.android.internal.R;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
import java.util.ArrayList;
-class WinAnimatorList extends ArrayList<WindowStateAnimator> {
-}
-
/**
* Keep track of animations and surface operations for a single WindowState.
**/
@@ -185,7 +180,7 @@
int mAttrType;
- public WindowStateAnimator(final WindowState win) {
+ WindowStateAnimator(final WindowState win) {
final WindowManagerService service = win.mService;
mService = service;
@@ -243,9 +238,7 @@
boolean isAnimating() {
return mAnimation != null
|| (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
- || (mAppAnimator != null &&
- (mAppAnimator.animation != null
- || mAppAnimator.mAppToken.inPendingTransaction));
+ || (mAppAnimator != null && mAppAnimator.isAnimating());
}
/** Is the window animating the DummyAnimation? */
@@ -482,7 +475,7 @@
mService.mPendingRemove.add(mWin);
mWin.mRemoveOnExit = false;
}
- mAnimator.hideWallpapersLocked(mWin);
+ mService.hideWallpapersLocked(mWin);
}
void hide() {
@@ -523,7 +516,7 @@
}
// This must be called while inside a transaction.
- boolean commitFinishDrawingLocked(long currentTime) {
+ boolean commitFinishDrawingLocked() {
if (DEBUG_STARTING_WINDOW &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
@@ -980,7 +973,7 @@
}
mSurfaceControl.destroy();
}
- mAnimator.hideWallpapersLocked(mWin);
+ mService.hideWallpapersLocked(mWin);
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window " + this
+ " surface " + mSurfaceControl + " session " + mSession
@@ -1006,7 +999,7 @@
WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
}
mPendingDestroySurface.destroy();
- mAnimator.hideWallpapersLocked(mWin);
+ mService.hideWallpapersLocked(mWin);
}
} catch (RuntimeException e) {
Slog.w(TAG, "Exception thrown when destroying Window "
@@ -1454,7 +1447,7 @@
hide();
} else if (w.mAttachedHidden || !w.isOnScreen()) {
hide();
- mAnimator.hideWallpapersLocked(w);
+ mService.hideWallpapersLocked(w);
// If we are waiting for this window to handle an
// orientation change, well, it is hidden, so
@@ -1626,13 +1619,8 @@
}
if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
- RuntimeException e = null;
- if (!WindowManagerService.HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
Slog.v(TAG, "performShow on " + this
- + ": mDrawState=" + mDrawState + " readyForDisplay="
+ + ": mDrawState=" + drawStateToString() + " readyForDisplay="
+ mWin.isReadyForDisplayIgnoringKeyguard()
+ " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING)
+ " during animation: policyVis=" + mWin.mPolicyVisibility
@@ -1643,7 +1631,8 @@
+ (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
+ " animating=" + mAnimating
+ " tok animating="
- + (mAppAnimator != null ? mAppAnimator.animating : false), e);
+ + (mAppAnimator != null ? mAppAnimator.animating : false) + " Callers="
+ + Debug.getCallers(3));
}
if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index f0e02bc..57ed876 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -39,7 +39,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.PrintWriter;
import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
/**
@@ -320,5 +322,23 @@
this.admin = admin;
this.packageName = admin.getPackageName();
}
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "admin=" + admin);
+ pw.println(prefix + "name=" + name);
+ pw.println();
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ if (mDeviceOwner != null) {
+ pw.println(prefix + "Device Owner: ");
+ mDeviceOwner.dump(prefix + " ", pw);
+ }
+ if (mProfileOwners != null) {
+ for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) {
+ pw.println(prefix + "Profile Owner (User " + entry.getKey() + "): ");
+ entry.getValue().dump(prefix + " ", pw);
+ }
+ }
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fbb6f7c..6dc54ce 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -78,6 +78,7 @@
import android.os.UserManager;
import android.provider.Settings;
import android.security.Credentials;
+import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
@@ -99,6 +100,7 @@
import com.android.internal.os.storage.ExternalStorageFormatter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
@@ -1579,15 +1581,16 @@
void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
// Ensure the status of the camera is synced down to the system. Interested native services
// should monitor this value and act accordingly.
- boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
+ String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
+ boolean systemState = SystemProperties.getBoolean(cameraPropertyForUser, false);
boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
if (cameraDisabled != systemState) {
long token = Binder.clearCallingIdentity();
try {
String value = cameraDisabled ? "1" : "0";
if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
- + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
- SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
+ + cameraPropertyForUser + "] = " + value);
+ SystemProperties.set(cameraPropertyForUser, value);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1918,13 +1921,11 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
validateQualityConstant(quality);
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordQuality != quality) {
@@ -1967,11 +1968,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLength != length) {
@@ -2014,11 +2013,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.passwordHistoryLength != length) {
@@ -2061,14 +2058,10 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
- if (timeout < 0) {
- throw new IllegalArgumentException("Timeout must be >= 0 ms");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
// Calling this API automatically bumps the expiration date
@@ -2230,11 +2223,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordUpperCase != length) {
@@ -2274,11 +2265,9 @@
}
public void setPasswordMinimumLowerCase(ComponentName who, int length) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLowerCase != length) {
@@ -2321,11 +2310,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordLetters != length) {
@@ -2368,11 +2355,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNumeric != length) {
@@ -2415,11 +2400,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordSymbols != length) {
@@ -2462,11 +2445,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
if (ap.minimumPasswordNonLetter != length) {
@@ -2559,11 +2540,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who,
@@ -2770,11 +2749,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
if (ap.maximumTimeToUnlock != timeMs) {
@@ -2953,9 +2930,7 @@
@Override
public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
@@ -2980,6 +2955,63 @@
return false;
}
+ @Override
+ public void choosePrivateKeyAlias(final int uid, final String host, int port, final String url,
+ final String alias, final IBinder response) {
+ // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers.
+ if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
+ return;
+ }
+
+ final UserHandle caller = Binder.getCallingUserHandle();
+ final ComponentName profileOwner = getProfileOwner(caller.getIdentifier());
+
+ if (profileOwner == null) {
+ sendPrivateKeyAliasResponse(null, response);
+ return;
+ }
+
+ Intent intent = new Intent(DeviceAdminReceiver.ACTION_CHOOSE_PRIVATE_KEY_ALIAS);
+ intent.setComponent(profileOwner);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_SENDER_UID, uid);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_HOST, host);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_PORT, port);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_URL, url);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_ALIAS, alias);
+ intent.putExtra(DeviceAdminReceiver.EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE, response);
+
+ final long id = Binder.clearCallingIdentity();
+ try {
+ mContext.sendOrderedBroadcastAsUser(intent, caller, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String chosenAlias = getResultData();
+ sendPrivateKeyAliasResponse(chosenAlias, response);
+ }
+ }, null, Activity.RESULT_OK, null, null);
+ } finally {
+ Binder.restoreCallingIdentity(id);
+ }
+ }
+
+ private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
+ final IKeyChainAliasCallback keyChainAliasResponse =
+ IKeyChainAliasCallback.Stub.asInterface(responseBinder);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ try {
+ keyChainAliasResponse.alias(alias);
+ } catch (Exception e) {
+ // Catch everything (not just RemoteException): caller could throw a
+ // RuntimeException back across processes.
+ Log.e(LOG_TAG, "error while responding to callback", e);
+ }
+ return null;
+ }
+ }.execute();
+ }
+
private void wipeDataLocked(boolean wipeExtRequested, String reason) {
// If the SD card is encrypted and non-removable, we have to force a wipe.
boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
@@ -3238,9 +3270,7 @@
return null;
}
synchronized(this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
// Only check if owner has set global proxy. We don't allow other users to set it.
DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
@@ -3376,12 +3406,10 @@
if (!mHasFeature) {
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
// Check for permissions
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// Only owner can set storage encryption
if (userHandle != UserHandle.USER_OWNER
|| UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
@@ -3512,11 +3540,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (ap.disableScreenCapture != disabled) {
@@ -3571,11 +3597,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (admin.requireAutoTime != required) {
@@ -3611,9 +3635,10 @@
/**
* The system property used to share the state of the camera. The native camera service
- * is expected to read this property and act accordingly.
+ * is expected to read this property and act accordingly. The userId should be appended
+ * to this key.
*/
- public static final String SYSTEM_PROP_DISABLE_CAMERA = "sys.secpolicy.camera.disabled";
+ public static final String SYSTEM_PROP_DISABLE_CAMERA_PREFIX = "sys.secpolicy.camera.off_";
/**
* Disables all device cameras according to the specified admin.
@@ -3622,11 +3647,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
if (ap.disableCamera != disabled) {
@@ -3671,12 +3694,10 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
enforceNotManagedProfile(userHandle, "disable keyguard features");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
if (ap.disabledKeyguardFeatures != which) {
@@ -3820,9 +3841,7 @@
@Override
public void clearDeviceOwner(String packageName) {
- if (packageName == null) {
- throw new NullPointerException("packageName is null");
- }
+ Preconditions.checkNotNull(packageName, "packageName is null");
try {
int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
if (uid != Binder.getCallingUid()) {
@@ -3947,12 +3966,9 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
- // Check for permissions
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
// Check if this is the profile owner who is calling
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userId = UserHandle.getCallingUserId();
@@ -3974,12 +3990,8 @@
@Override
public void setProfileName(ComponentName who, String profileName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int userId = UserHandle.getCallingUserId();
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// Check if this is the profile owner (includes device owner).
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -4041,16 +4053,18 @@
}
/**
- * Device owner can only be set on an unprovisioned device, unless it was initiated by "adb", in
- * which case we allow it if no account is associated with the device.
+ * Device owner can only be set on an unprovisioned device. However, if initiated via "adb",
+ * we also allow it if no accounts or additional users are present on the device.
*/
private boolean allowedToSetDeviceOwnerOnDevice() {
- int callingId = Binder.getCallingUid();
- if (callingId == Process.SHELL_UID || callingId == Process.ROOT_UID) {
- return AccountManager.get(mContext).getAccounts().length == 0;
- } else {
- return !hasUserSetupCompleted(UserHandle.USER_OWNER);
+ if (!hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ return true;
}
+
+ int callingId = Binder.getCallingUid();
+ return (callingId == Process.SHELL_UID || callingId == Process.ROOT_UID)
+ && mUserManager.getUserCount() == 1
+ && AccountManager.get(mContext).getAccounts().length == 0;
}
private void enforceCrossUserPermission(int userHandle) {
@@ -4127,7 +4141,9 @@
synchronized (this) {
p.println("Current Device Policy Manager state:");
-
+ if (mDeviceOwner != null) {
+ mDeviceOwner.dump(" ", pw);
+ }
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
@@ -4155,12 +4171,9 @@
@Override
public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4177,12 +4190,9 @@
@Override
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4199,12 +4209,9 @@
@Override
public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4221,15 +4228,11 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(admin, "admin is null");
+ Preconditions.checkNotNull(agent, "agent is null");
final int userHandle = UserHandle.getCallingUserId();
enforceNotManagedProfile(userHandle, "set trust agent configuration");
synchronized (this) {
- if (admin == null) {
- throw new NullPointerException("admin is null");
- }
- if (agent == null) {
- throw new NullPointerException("agent is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
@@ -4243,10 +4246,8 @@
if (!mHasFeature) {
return null;
}
+ Preconditions.checkNotNull(agent, "agent null");
enforceCrossUserPermission(userHandle);
- if (agent == null) {
- throw new NullPointerException("agent is null");
- }
synchronized (this) {
final String componentName = agent.flattenToString();
@@ -4299,10 +4300,8 @@
@Override
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
int userHandle = UserHandle.getCallingUserId();
@@ -4324,11 +4323,9 @@
}
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
@@ -4351,11 +4348,9 @@
}
public void clearCrossProfileIntentFilters(ComponentName who) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IPackageManager pm = AppGlobals.getPackageManager();
long id = Binder.clearCallingIdentity();
@@ -4425,9 +4420,7 @@
if (!mHasFeature) {
return false;
}
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
if (packageList != null) {
int userId = UserHandle.getCallingUserId();
@@ -4472,10 +4465,7 @@
if (!mHasFeature) {
return null;
}
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -4580,9 +4570,7 @@
if (!mHasFeature) {
return false;
}
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
// TODO When InputMethodManager supports per user calls remove
// this restriction.
@@ -4625,10 +4613,7 @@
if (!mHasFeature) {
return null;
}
-
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -4701,10 +4686,8 @@
@Override
public UserHandle createUser(ComponentName who, String name) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4755,10 +4738,8 @@
@Override
public boolean removeUser(ComponentName who, UserHandle userHandle) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4772,10 +4753,8 @@
@Override
public boolean switchUser(ComponentName who, UserHandle userHandle) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4796,12 +4775,10 @@
@Override
public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4815,12 +4792,10 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
final int userHandle = user.getIdentifier();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
@@ -4922,11 +4897,9 @@
@Override
public boolean setApplicationHidden(ComponentName who, String packageName,
boolean hidden) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4945,11 +4918,9 @@
@Override
public boolean isApplicationHidden(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -4968,11 +4939,8 @@
@Override
public void enableSystemApp(ComponentName who, String packageName) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5013,11 +4981,8 @@
@Override
public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5084,10 +5049,8 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (disabled) {
@@ -5125,12 +5088,9 @@
@Override
public void setUninstallBlocked(ComponentName who, String packageName,
boolean uninstallBlocked) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
final int userId = UserHandle.getCallingUserId();
-
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
@@ -5177,10 +5137,8 @@
if (!mHasFeature) {
return;
}
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableCallerId != disabled) {
@@ -5195,12 +5153,8 @@
if (!mHasFeature) {
return false;
}
-
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
return admin.disableCallerId;
@@ -5221,13 +5175,11 @@
* Sets which packages may enter lock task mode.
*
* This function can only be called by the device owner.
- * @param components The list of components allowed to enter lock task mode.
+ * @param packages The list of packages allowed to enter lock task mode.
*/
public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
int userHandle = Binder.getCallingUserHandle().getIdentifier();
@@ -5249,15 +5201,13 @@
* This function returns the list of components allowed to start the task lock mode.
*/
public String[] getLockTaskPackages(ComponentName who) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
int userHandle = Binder.getCallingUserHandle().getIdentifier();
DevicePolicyData policy = getUserData(userHandle);
- return policy.mLockTaskPackages.toArray(new String[0]);
+ return policy.mLockTaskPackages.toArray(new String[policy.mLockTaskPackages.size()]);
}
}
@@ -5313,11 +5263,9 @@
@Override
public void setGlobalSetting(ComponentName who, String setting, String value) {
final ContentResolver contentResolver = mContext.getContentResolver();
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)) {
@@ -5336,13 +5284,11 @@
@Override
public void setSecureSetting(ComponentName who, String setting, String value) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
int callingUserId = UserHandle.getCallingUserId();
final ContentResolver contentResolver = mContext.getContentResolver();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5367,10 +5313,8 @@
@Override
public void setMasterVolumeMuted(ComponentName who, boolean on) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
IAudioService iAudioService = IAudioService.Stub.asInterface(
@@ -5387,12 +5331,8 @@
@Override
public boolean isMasterVolumeMuted(ComponentName who) {
- final ContentResolver contentResolver = mContext.getContentResolver();
-
+ Preconditions.checkNotNull(who, "ComponentName is null");
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
AudioManager audioManager =
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index c6f6b85..0aa8862 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -26,7 +26,7 @@
import android.hardware.usb.UsbInterface;
import android.media.AudioSystem;
import android.media.IAudioService;
-import android.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceInfo;
import android.os.FileObserver;
import android.os.Bundle;
import android.os.IBinder;
@@ -153,7 +153,7 @@
// audioDevice - the AudioDevice that was added or removed
// enabled - if true, we're connecting a device (it's arrived), else disconnecting
private void notifyDeviceState(UsbAudioDevice audioDevice, boolean enabled) {
- if (DEBUG) {
+ if (DEBUG) {
Slog.d(TAG, "notifyDeviceState " + enabled + " " + audioDevice);
}
@@ -422,7 +422,7 @@
}
/* package */ void usbDeviceRemoved(UsbDevice usbDevice) {
- if (DEBUG) {
+ if (DEBUG) {
Slog.d(TAG, "deviceRemoved(): " + usbDevice);
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 2fb6dbf..43c7336 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -31,7 +31,6 @@
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
-import android.midi.MidiDeviceInfo;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
@@ -732,6 +731,8 @@
id = com.android.internal.R.string.usb_mtp_notification_title;
} else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP)) {
id = com.android.internal.R.string.usb_ptp_notification_title;
+ } else if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI)) {
+ id = com.android.internal.R.string.usb_midi_notification_title;
} else if (containsFunction(mCurrentFunctions,
UsbManager.USB_FUNCTION_MASS_STORAGE)) {
id = com.android.internal.R.string.usb_cd_installer_notification_title;
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 8d44905..e17abc0 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -17,12 +17,12 @@
package com.android.server.usb;
import android.content.Context;
-import android.midi.MidiDeviceInfo;
-import android.midi.MidiDeviceServer;
-import android.midi.MidiManager;
-import android.midi.MidiPort;
-import android.midi.MidiReceiver;
-import android.midi.MidiSender;
+import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceServer;
+import android.media.midi.MidiManager;
+import android.media.midi.MidiPort;
+import android.media.midi.MidiReceiver;
+import android.media.midi.MidiSender;
import android.os.Bundle;
import android.system.ErrnoException;
import android.system.Os;
@@ -112,7 +112,7 @@
MidiReceiver receiver = new MidiReceiver() {
@Override
- public void onPost(byte[] data, int offset, int count, long timestamp)
+ public void post(byte[] data, int offset, int count, long timestamp)
throws IOException {
// FIXME - timestamps are ignored, future posting not supported yet.
mOutputStreams[portNumberF].write(data, offset, count);
@@ -137,7 +137,7 @@
pfd.revents = 0;
int count = mInputStreams[index].read(buffer);
- mOutputPortReceivers[index].onPost(buffer, 0, count,
+ mOutputPortReceivers[index].post(buffer, 0, count,
System.nanoTime());
} else if ((pfd.revents & (OsConstants.POLLERR
| OsConstants.POLLHUP)) != 0) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index c32ba67..fd990d7 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -129,12 +129,14 @@
}
public void initForUser(int userHandle) {
- if (DEBUG) Slog.i(TAG, "initForUser user=" + userHandle);
+ if (DEBUG) Slog.d(TAG, "**************** initForUser user=" + userHandle);
String curInteractorStr = Settings.Secure.getStringForUser(
mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
ComponentName curRecognizer = getCurRecognizer(userHandle);
VoiceInteractionServiceInfo curInteractorInfo = null;
+ if (DEBUG) Slog.d(TAG, "curInteractorStr=" + curInteractorStr
+ + " curRecognizer=" + curRecognizer);
if (curInteractorStr == null && curRecognizer != null
&& !ActivityManager.isLowRamDeviceStatic()) {
// If there is no interactor setting, that means we are upgrading
@@ -148,6 +150,8 @@
// Looks good! We'll apply this one. To make it happen, we clear the
// recognizer so that we don't think we have anything set and will
// re-apply the settings.
+ if (DEBUG) Slog.d(TAG, "No set interactor, found avail: "
+ + curInteractorInfo.getServiceInfo().name);
curRecognizer = null;
}
}
@@ -156,6 +160,7 @@
// enabled; if it is, turn it off.
if (ActivityManager.isLowRamDeviceStatic() && curInteractorStr != null) {
if (!TextUtils.isEmpty(curInteractorStr)) {
+ if (DEBUG) Slog.d(TAG, "Svelte device; disabling interactor");
setCurInteractor(null, userHandle);
curInteractorStr = "";
}
@@ -178,8 +183,11 @@
}
// If the apps for the currently set components still exist, then all is okay.
if (recognizerInfo != null && (curInteractor == null || interactorInfo != null)) {
+ if (DEBUG) Slog.d(TAG, "Current interactor/recognizer okay, done!");
return;
}
+ if (DEBUG) Slog.d(TAG, "Bad recognizer (" + recognizerInfo + ") or interactor ("
+ + interactorInfo + ")");
}
// Initializing settings, look for an interactor first (but only on non-svelte).
@@ -316,7 +324,7 @@
if (TextUtils.isEmpty(curInteractor)) {
return null;
}
- if (DEBUG) Slog.i(TAG, "getCurInteractor curInteractor=" + curInteractor
+ if (DEBUG) Slog.d(TAG, "getCurInteractor curInteractor=" + curInteractor
+ " user=" + userHandle);
return ComponentName.unflattenFromString(curInteractor);
}
@@ -325,7 +333,7 @@
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE,
comp != null ? comp.flattenToShortString() : "", userHandle);
- if (DEBUG) Slog.i(TAG, "setCurInteractor comp=" + comp
+ if (DEBUG) Slog.d(TAG, "setCurInteractor comp=" + comp
+ " user=" + userHandle);
}
@@ -363,7 +371,7 @@
if (TextUtils.isEmpty(curRecognizer)) {
return null;
}
- if (DEBUG) Slog.i(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
+ if (DEBUG) Slog.d(TAG, "getCurRecognizer curRecognizer=" + curRecognizer
+ " user=" + userHandle);
return ComponentName.unflattenFromString(curRecognizer);
}
@@ -372,12 +380,12 @@
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.VOICE_RECOGNITION_SERVICE,
comp != null ? comp.flattenToShortString() : "", userHandle);
- if (DEBUG) Slog.i(TAG, "setCurRecognizer comp=" + comp
+ if (DEBUG) Slog.d(TAG, "setCurRecognizer comp=" + comp
+ " user=" + userHandle);
}
@Override
- public void startSession(IVoiceInteractionService service, Bundle args) {
+ public void startSession(IVoiceInteractionService service, Bundle args, int flags) {
synchronized (this) {
if (mImpl == null || mImpl.mService == null
|| service.asBinder() != mImpl.mService.asBinder()) {
@@ -388,7 +396,7 @@
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.startSessionLocked(callingPid, callingUid, args);
+ mImpl.startSessionLocked(callingPid, callingUid, args, flags);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -692,7 +700,7 @@
@Override
public void onSomePackagesChanged() {
int userHandle = getChangingUserId();
- if (DEBUG) Slog.i(TAG, "onSomePackagesChanged user=" + userHandle);
+ if (DEBUG) Slog.d(TAG, "onSomePackagesChanged user=" + userHandle);
ComponentName curInteractor = getCurInteractor(userHandle);
ComponentName curRecognizer = getCurRecognizer(userHandle);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index b36b611..e80f702 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -43,6 +43,7 @@
import android.view.WindowManager;
import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.os.IResultReceiver;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -103,13 +104,33 @@
final class SessionConnection implements ServiceConnection {
final IBinder mToken = new Binder();
final Bundle mArgs;
+ final int mFlags;
boolean mBound;
IVoiceInteractionSessionService mService;
IVoiceInteractionSession mSession;
IVoiceInteractor mInteractor;
+ boolean mHaveAssistData;
+ Bundle mAssistData;
- SessionConnection(Bundle args) {
+ final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ synchronized (mLock) {
+ mHaveAssistData = true;
+ mAssistData = resultData;
+ if (mSession != null) {
+ try {
+ mSession.handleAssist(resultData);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+ };
+
+ SessionConnection(Bundle args, int flags) {
mArgs = args;
+ mFlags = flags;
Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
serviceIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(serviceIntent, this,
@@ -121,6 +142,14 @@
} catch (RemoteException e) {
Slog.w(TAG, "Failed adding window token", e);
}
+ if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) {
+ try {
+ mAm.requestAssistContextExtras(0, mAssistReceiver);
+ } catch (RemoteException e) {
+ }
+ } else {
+ mHaveAssistData = true;
+ }
} else {
Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent);
}
@@ -132,7 +161,7 @@
mService = IVoiceInteractionSessionService.Stub.asInterface(service);
if (mActiveSession == this) {
try {
- mService.newSession(mToken, mArgs);
+ mService.newSession(mToken, mArgs, mFlags);
} catch (RemoteException e) {
Slog.w(TAG, "Failed adding window token", e);
}
@@ -176,12 +205,17 @@
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
pw.print(prefix); pw.print("mArgs="); pw.println(mArgs);
+ pw.print(prefix); pw.print("mFlags=0x"); pw.println(Integer.toHexString(mFlags));
pw.print(prefix); pw.print("mBound="); pw.println(mBound);
if (mBound) {
pw.print(prefix); pw.print("mService="); pw.println(mService);
pw.print(prefix); pw.print("mSession="); pw.println(mSession);
pw.print(prefix); pw.print("mInteractor="); pw.println(mInteractor);
}
+ pw.print(prefix); pw.print("mHaveAssistData="); pw.println(mHaveAssistData);
+ if (mHaveAssistData) {
+ pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData);
+ }
}
};
@@ -222,12 +256,12 @@
mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
}
- public void startSessionLocked(int callingPid, int callingUid, Bundle args) {
+ public void startSessionLocked(int callingPid, int callingUid, Bundle args, int flags) {
if (mActiveSession != null) {
mActiveSession.cancel();
mActiveSession = null;
}
- mActiveSession = new SessionConnection(args);
+ mActiveSession = new SessionConnection(args, flags);
}
public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
@@ -238,6 +272,12 @@
}
mActiveSession.mSession = session;
mActiveSession.mInteractor = interactor;
+ if (mActiveSession.mHaveAssistData) {
+ try {
+ session.handleAssist(mActiveSession.mAssistData);
+ } catch (RemoteException e) {
+ }
+ }
return true;
}
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 570f5fd..4600b72 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -80,6 +80,9 @@
* ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
* collide with values generated on other phones or after a data wipe of a given phone.
*
+ * Important: A non-unique identifier could cause non-deterministic call-log backup/restore
+ * behavior.
+ *
* @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
*/
public String getId() {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6c5f1c6..bcc1ccc4 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -83,6 +83,12 @@
"android.telecom.action.SHOW_CALL_SETTINGS";
/**
+ * The {@link android.content.Intent} action used to show the respond via SMS settings page.
+ */
+ public static final String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS =
+ "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
+
+ /**
* The {@link android.content.Intent} action used to show the settings page used to configure
* {@link PhoneAccount} preferences.
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 94691c0..dda9626 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.telecom.PhoneAccount;
import android.util.Log;
import com.android.internal.telecom.ITelecomService;
@@ -3765,7 +3766,7 @@
/**
* Returns the IMS Registration Status
- *@hide
+ * @hide
*/
public boolean isImsRegistered() {
try {
@@ -4116,4 +4117,21 @@
ServiceState.rilRadioTechnologyToString(type));
}
}
+
+ /**
+ * Returns the subscription ID for the given phone account.
+ * @hide
+ */
+ public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
+ int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ retval = service.getSubIdForPhoneAccount(phoneAccount);
+ }
+ } catch (RemoteException e) {
+ }
+
+ return retval;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bf3ee09..62c8746 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.os.Bundle;
+import android.telecom.PhoneAccount;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.NeighboringCellInfo;
@@ -879,4 +880,9 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
String getDeviceId();
+
+ /**
+ * Returns the subscription ID associated with the specified PhoneAccount.
+ */
+ int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
}
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
index bc0e4e4..5f3d0d9 100644
--- a/tests/CoreTests/android/Android.mk
+++ b/tests/CoreTests/android/Android.mk
@@ -6,7 +6,7 @@
LOCAL_SRC_FILES := \
$(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt
+LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle conscrypt org.apache.http.legacy
LOCAL_PACKAGE_NAME := CoreTests
diff --git a/tests/CoreTests/android/AndroidManifest.xml b/tests/CoreTests/android/AndroidManifest.xml
index 8331f0c..bf46d15 100644
--- a/tests/CoreTests/android/AndroidManifest.xml
+++ b/tests/CoreTests/android/AndroidManifest.xml
@@ -35,6 +35,7 @@
<application>
<uses-library android:name="android.test.runner" />
+ <uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>
<instrumentation
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
index 7177fc8f..1f2b939 100644
--- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -14,13 +14,13 @@
android:id="@+id/clickable1"
android:layout_width="100dp"
android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackground"/>
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
<View
android:id="@+id/clickable2"
android:translationX="50dp"
android:translationY="10dp"
android:layout_width="150dp"
android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackground"/>
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
</FrameLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
index 4feac68..b7d7f98 100644
--- a/tests/OneMedia/Android.mk
+++ b/tests/OneMedia/Android.mk
@@ -12,6 +12,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-media-protocols
+LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
+
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 95072a4..ef3fad5 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -13,6 +13,8 @@
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
+
+ <uses-library android:name="org.apache.http.legacy" android:required="false" />
<activity
android:name="com.android.onemedia.OnePlayerActivity"
android:label="@string/app_name" >
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
index 06d31a4..adf572c 100644
--- a/tests/VoiceInteraction/AndroidManifest.xml
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -12,11 +12,19 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity android:name="SettingsActivity"
- android:label="Voice Interaction Settings"
+ <activity android:name="AssistProxyActivity"
+ android:label="Test Assist Proxy"
+ android:theme="@android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:noHistory="true">
<intent-filter>
+ <action android:name="android.intent.action.ASSIST" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name="SettingsActivity"
+ android:label="Voice Interaction Settings">
+ <intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -44,7 +52,7 @@
<meta-data android:name="android.speech" android:resource="@xml/recognition_service" />
</service>
<activity android:name="TestInteractionActivity" android:label="Voice Interaction Target"
- android:theme="@android:style/Theme.Material.Light.Voice">
+ android:theme="@android:style/Theme.Material.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
index d55736f..c4e280e 100644
--- a/tests/VoiceInteraction/res/layout/test_interaction.xml
+++ b/tests/VoiceInteraction/res/layout/test_interaction.xml
@@ -32,7 +32,6 @@
android:layout_weight="1"
android:layout_marginTop="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="#ffffffff"
/>
<Button android:id="@+id/complete"
diff --git a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
index 002f350..10571765 100644
--- a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
+++ b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
@@ -15,24 +15,46 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <FrameLayout android:layout_width="fill_parent"
+ <com.android.test.voiceinteraction.AssistVisualizer android:id="@+id/assist_visualizer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="8dp">
+ android:fitsSystemWindows="true">
- <LinearLayout android:id="@+id/content"
- android:layout_width="fill_parent"
- android:layout_height="match_parent"
+ <FrameLayout android:id="@+id/top_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:orientation="vertical"
+ android:background="#ffffffff"
+ android:elevation="8dp"
+ >
+
+ <Button android:id="@+id/start"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|right"
+ android:text="@string/start"
+ />
+
+ </FrameLayout>
+
+ <LinearLayout android:id="@+id/bottom_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
android:orientation="vertical"
android:background="#ffffffff"
android:elevation="8dp"
>
<TextView android:id="@+id/text"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
@@ -40,11 +62,6 @@
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
android:orientation="horizontal">
- <Button android:id="@+id/start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/start"
- />
<Button android:id="@+id/confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java
new file mode 100644
index 0000000..fc04ff5
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistProxyActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class AssistProxyActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ Intent intent = new Intent(this, MainInteractionService.class);
+ intent.setAction(Intent.ACTION_ASSIST);
+ intent.putExtras(getIntent());
+ startService(new Intent(this, MainInteractionService.class));
+ }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
new file mode 100644
index 0000000..5d5ae2f
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.annotation.Nullable;
+import android.app.AssistData;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+import java.util.ArrayList;
+
+public class AssistVisualizer extends View {
+ static final String TAG = "AssistVisualizer";
+
+ AssistData mAssistData;
+ final Paint mFramePaint = new Paint();
+ final ArrayList<Rect> mTextRects = new ArrayList<>();
+ final int[] mTmpLocation = new int[2];
+
+ public AssistVisualizer(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ setWillNotDraw(false);
+ mFramePaint.setColor(0xffff0000);
+ mFramePaint.setStyle(Paint.Style.STROKE);
+ mFramePaint.setStrokeWidth(0);
+ }
+
+ public void setAssistData(AssistData ad) {
+ mAssistData = ad;
+ mTextRects.clear();
+ final int N = ad.getWindowCount();
+ if (N > 0) {
+ AssistData.ViewNode window = new AssistData.ViewNode();
+ for (int i=0; i<N; i++) {
+ ad.getWindowAt(i, window);
+ buildTextRects(window, 0, 0);
+ }
+ }
+ }
+
+ void buildTextRects(AssistData.ViewNode root, int parentLeft, int parentTop) {
+ if (root.getVisibility() != View.VISIBLE) {
+ return;
+ }
+ int left = parentLeft+root.getLeft();
+ int top = parentTop+root.getTop();
+ Log.d(TAG, "View " + root.getClassName() + ": " + left + ", " + top);
+ if (root.getText() != null) {
+ Rect r = new Rect(left, top, left+root.getWidth(), top+root.getHeight());
+ Log.d(TAG, "Text Rect " + r.toShortString() + ": " + root.getText());
+ mTextRects.add(r);
+ }
+ final int N = root.getChildCount();
+ if (N > 0) {
+ left -= root.getScrollX();
+ top -= root.getScrollY();
+ AssistData.ViewNode child = new AssistData.ViewNode();
+ for (int i=0; i<N; i++) {
+ root.getChildAt(i, child);
+ buildTextRects(child, left, top);
+ }
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ getLocationOnScreen(mTmpLocation);
+ final int N = mTextRects.size();
+ for (int i=0; i<N; i++) {
+ Rect r = mTextRects.get(i);
+ canvas.drawRect(r.left-mTmpLocation[0], r.top-mTmpLocation[1],
+ r.right-mTmpLocation[0], r.bottom-mTmpLocation[1], mFramePaint);
+ }
+ }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 4639114..2cab3ea 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -16,6 +16,7 @@
package com.android.test.voiceinteraction;
+import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.service.voice.AlwaysOnHotwordDetector;
@@ -74,9 +75,19 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Bundle args = new Bundle();
- args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
- startSession(args);
+ if (isActiveService(this, new ComponentName(this, getClass()))) {
+ Bundle args = new Bundle();
+ args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
+ args.putBundle("assist", intent.getExtras());
+ Bundle assistContext = intent.getBundleExtra(Intent.EXTRA_ASSIST_CONTEXT);
+ int startFlags = 0;
+ if (assistContext == null) {
+ startFlags |= START_WITH_ASSIST;
+ }
+ startSession(args, startFlags);
+ } else {
+ Log.w(TAG, "Not starting -- not current voice interaction service");
+ }
stopSelf(startId);
return START_NOT_STICKY;
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index d20906e..1aeb98a 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -16,6 +16,7 @@
package com.android.test.voiceinteraction;
+import android.app.AssistData;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -31,12 +32,17 @@
Intent mStartIntent;
View mContentView;
+ AssistVisualizer mAssistVisualizer;
+ View mTopContent;
+ View mBottomContent;
TextView mText;
Button mStartButton;
Button mConfirmButton;
Button mCompleteButton;
Button mAbortButton;
+ AssistData mAssistData;
+
static final int STATE_IDLE = 0;
static final int STATE_LAUNCHING = 1;
static final int STATE_CONFIRM = 2;
@@ -52,15 +58,25 @@
}
@Override
- public void onCreate(Bundle args) {
+ public void onCreate(Bundle args, int startFlags) {
super.onCreate(args);
showWindow();
mStartIntent = args.getParcelable("intent");
+ Bundle assist = args.getBundle("assist");
+ if (assist != null) {
+ parseAssistData(assist);
+ }
}
@Override
public View onCreateContentView() {
mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null);
+ mAssistVisualizer = (AssistVisualizer)mContentView.findViewById(R.id.assist_visualizer);
+ if (mAssistData != null) {
+ mAssistVisualizer.setAssistData(mAssistData);
+ }
+ mTopContent = mContentView.findViewById(R.id.top_content);
+ mBottomContent = mContentView.findViewById(R.id.bottom_content);
mText = (TextView)mContentView.findViewById(R.id.text);
mStartButton = (Button)mContentView.findViewById(R.id.start);
mStartButton.setOnClickListener(this);
@@ -74,7 +90,34 @@
return mContentView;
}
+ @Override
+ public void onHandleAssist(Bundle assistBundle) {
+ if (assistBundle != null) {
+ parseAssistData(assistBundle);
+ } else {
+ Log.i(TAG, "onHandleAssist: NO ASSIST BUNDLE");
+ }
+ }
+
+ void parseAssistData(Bundle assistBundle) {
+ Bundle assistContext = assistBundle.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
+ if (assistContext != null) {
+ mAssistData = AssistData.getAssistData(assistContext);
+ mAssistData.dump();
+ if (mAssistVisualizer != null) {
+ mAssistVisualizer.setAssistData(mAssistData);
+ }
+ }
+ }
+
void updateState() {
+ if (mState == STATE_IDLE) {
+ mTopContent.setVisibility(View.VISIBLE);
+ mBottomContent.setVisibility(View.GONE);
+ } else {
+ mTopContent.setVisibility(View.GONE);
+ mBottomContent.setVisibility(View.VISIBLE);
+ }
mStartButton.setEnabled(mState == STATE_IDLE);
mConfirmButton.setEnabled(mState == STATE_CONFIRM || mState == STATE_COMMAND);
mAbortButton.setEnabled(mState == STATE_ABORT_VOICE);
@@ -109,6 +152,15 @@
}
@Override
+ public void onComputeInsets(Insets outInsets) {
+ super.onComputeInsets(outInsets);
+ if (mState != STATE_IDLE) {
+ outInsets.contentInsets.top = mBottomContent.getTop();
+ outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT;
+ }
+ }
+
+ @Override
public boolean[] onGetSupportedCommands(Caller caller, String[] commands) {
return new boolean[commands.length];
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index 783c78e..8522cdc 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -57,11 +57,6 @@
mCompleteButton = (Button)findViewById(R.id.complete);
mCompleteButton.setOnClickListener(this);
- // Framework should take care of these.
- getWindow().setGravity(Gravity.TOP);
- getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
-
mInteractor = getVoiceInteractor();
VoiceInteractor.ConfirmationRequest req = new VoiceInteractor.ConfirmationRequest(
"This is a confirmation", null) {
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 393d2ec..5c6d870 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -48,8 +48,9 @@
class Field():
- def __init__(self, clazz, raw, blame):
+ def __init__(self, clazz, line, raw, blame):
self.clazz = clazz
+ self.line = line
self.raw = raw.strip(" {;")
self.blame = blame
@@ -73,8 +74,9 @@
class Method():
- def __init__(self, clazz, raw, blame):
+ def __init__(self, clazz, line, raw, blame):
self.clazz = clazz
+ self.line = line
self.raw = raw.strip(" {;")
self.blame = blame
@@ -110,8 +112,9 @@
class Class():
- def __init__(self, pkg, raw, blame):
+ def __init__(self, pkg, line, raw, blame):
self.pkg = pkg
+ self.line = line
self.raw = raw.strip(" {;")
self.blame = blame
self.ctors = []
@@ -129,10 +132,14 @@
if "extends" in raw:
self.extends = raw[raw.index("extends")+1]
+ self.extends_path = self.extends.split(".")
else:
self.extends = None
+ self.extends_path = []
self.fullname = self.pkg.name + "." + self.fullname
+ self.fullname_path = self.fullname.split(".")
+
self.name = self.fullname[self.fullname.rindex(".")+1:]
def __repr__(self):
@@ -140,75 +147,110 @@
class Package():
- def __init__(self, raw, blame):
+ def __init__(self, line, raw, blame):
+ self.line = line
self.raw = raw.strip(" {;")
self.blame = blame
raw = raw.split()
self.name = raw[raw.index("package")+1]
+ self.name_path = self.name.split(".")
def __repr__(self):
return self.raw
-def parse_api(fn):
+def _parse_stream(f, clazz_cb=None):
+ line = 0
api = {}
pkg = None
clazz = None
blame = None
re_blame = re.compile("^([a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
+ for raw in f:
+ line += 1
+ raw = raw.rstrip()
+ match = re_blame.match(raw)
+ if match is not None:
+ blame = match.groups()[0:2]
+ raw = match.groups()[2]
+ else:
+ blame = None
- with open(fn) as f:
- for raw in f.readlines():
- raw = raw.rstrip()
- match = re_blame.match(raw)
- if match is not None:
- blame = match.groups()[0:2]
- raw = match.groups()[2]
- else:
- blame = None
-
- if raw.startswith("package"):
- pkg = Package(raw, blame)
- elif raw.startswith(" ") and raw.endswith("{"):
- clazz = Class(pkg, raw, blame)
+ if raw.startswith("package"):
+ pkg = Package(line, raw, blame)
+ elif raw.startswith(" ") and raw.endswith("{"):
+ # When provided with class callback, we treat as incremental
+ # parse and don't build up entire API
+ if clazz and clazz_cb:
+ clazz_cb(clazz)
+ clazz = Class(pkg, line, raw, blame)
+ if not clazz_cb:
api[clazz.fullname] = clazz
- elif raw.startswith(" ctor"):
- clazz.ctors.append(Method(clazz, raw, blame))
- elif raw.startswith(" method"):
- clazz.methods.append(Method(clazz, raw, blame))
- elif raw.startswith(" field"):
- clazz.fields.append(Field(clazz, raw, blame))
+ elif raw.startswith(" ctor"):
+ clazz.ctors.append(Method(clazz, line, raw, blame))
+ elif raw.startswith(" method"):
+ clazz.methods.append(Method(clazz, line, raw, blame))
+ elif raw.startswith(" field"):
+ clazz.fields.append(Field(clazz, line, raw, blame))
+
+ # Handle last trailing class
+ if clazz and clazz_cb:
+ clazz_cb(clazz)
return api
+class Failure():
+ def __init__(self, sig, clazz, detail, error, rule, msg):
+ self.sig = sig
+ self.error = error
+ self.rule = rule
+ self.msg = msg
+
+ if error:
+ self.head = "Error %s" % (rule) if rule else "Error"
+ dump = "%s%s:%s %s" % (format(fg=RED, bg=BLACK, bold=True), self.head, format(reset=True), msg)
+ else:
+ self.head = "Warning %s" % (rule) if rule else "Warning"
+ dump = "%s%s:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), self.head, format(reset=True), msg)
+
+ self.line = clazz.line
+ blame = clazz.blame
+ if detail is not None:
+ dump += "\n in " + repr(detail)
+ self.line = detail.line
+ blame = detail.blame
+ dump += "\n in " + repr(clazz)
+ dump += "\n in " + repr(clazz.pkg)
+ dump += "\n at line " + repr(self.line)
+ if blame is not None:
+ dump += "\n last modified by %s in %s" % (blame[1], blame[0])
+
+ self.dump = dump
+
+ def __repr__(self):
+ return self.dump
+
+
failures = {}
-def _fail(clazz, detail, msg):
+def _fail(clazz, detail, error, rule, msg):
"""Records an API failure to be processed later."""
global failures
sig = "%s-%s-%s" % (clazz.fullname, repr(detail), msg)
sig = sig.replace(" deprecated ", " ")
- res = msg
- blame = clazz.blame
- if detail is not None:
- res += "\n in " + repr(detail)
- blame = detail.blame
- res += "\n in " + repr(clazz)
- res += "\n in " + repr(clazz.pkg)
- if blame is not None:
- res += "\n last modified by %s in %s" % (blame[1], blame[0])
- failures[sig] = res
+ failures[sig] = Failure(sig, clazz, detail, error, rule, msg)
-def warn(clazz, detail, msg):
- _fail(clazz, detail, "%sWarning:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), format(reset=True), msg))
-def error(clazz, detail, msg):
- _fail(clazz, detail, "%sError:%s %s" % (format(fg=RED, bg=BLACK, bold=True), format(reset=True), msg))
+def warn(clazz, detail, rule, msg):
+ _fail(clazz, detail, False, rule, msg)
+
+def error(clazz, detail, rule, msg):
+ _fail(clazz, detail, True, rule, msg)
def verify_constants(clazz):
@@ -218,13 +260,13 @@
for f in clazz.fields:
if "static" in f.split and "final" in f.split:
if re.match("[A-Z0-9_]+", f.name) is None:
- error(clazz, f, "Constant field names should be FOO_NAME")
+ error(clazz, f, "C2", "Constant field names must be FOO_NAME")
def verify_enums(clazz):
"""Enums are bad, mmkay?"""
if "extends java.lang.Enum" in clazz.raw:
- error(clazz, None, "Enums are not allowed")
+ error(clazz, None, "F5", "Enums are not allowed")
def verify_class_names(clazz):
@@ -234,9 +276,9 @@
if re.match("android\.R\.[a-z]+", clazz.fullname): return
if re.search("[A-Z]{2,}", clazz.name) is not None:
- warn(clazz, None, "Class name style should be Mtp not MTP")
+ warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
if re.match("[^A-Z]", clazz.name):
- error(clazz, None, "Class must start with uppercase char")
+ error(clazz, None, "S1", "Class must start with uppercase char")
def verify_method_names(clazz):
@@ -247,9 +289,9 @@
for m in clazz.methods:
if re.search("[A-Z]{2,}", m.name) is not None:
- warn(clazz, m, "Method name style should be getMtu() instead of getMTU()")
+ warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()")
if re.match("[^a-z]", m.name):
- error(clazz, m, "Method name must start with lowercase char")
+ error(clazz, m, "S1", "Method name must start with lowercase char")
def verify_callbacks(clazz):
@@ -259,17 +301,17 @@
if clazz.fullname == "android.speech.tts.SynthesisCallback": return
if clazz.name.endswith("Callbacks"):
- error(clazz, None, "Class name must not be plural")
+ error(clazz, None, "L1", "Callback class names should be singular")
if clazz.name.endswith("Observer"):
- warn(clazz, None, "Class should be named FooCallback")
+ warn(clazz, None, "L1", "Class should be named FooCallback")
if clazz.name.endswith("Callback"):
if "interface" in clazz.split:
- error(clazz, None, "Callback must be abstract class to enable extension in future API levels")
+ error(clazz, None, "CL3", "Callbacks must be abstract class to enable extension in future API levels")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "Callback method names must be onFoo() style")
+ error(clazz, m, "L1", "Callback method names must be onFoo() style")
def verify_listeners(clazz):
@@ -281,16 +323,16 @@
if clazz.name.endswith("Listener"):
if " abstract class " in clazz.raw:
- error(clazz, None, "Listener should be an interface, otherwise renamed Callback")
+ error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "Listener method names must be onFoo() style")
+ error(clazz, m, "L1", "Listener method names must be onFoo() style")
if len(clazz.methods) == 1 and clazz.name.startswith("On"):
m = clazz.methods[0]
if (m.name + "Listener").lower() != clazz.name.lower():
- error(clazz, m, "Single listener method name should match class name")
+ error(clazz, m, "L1", "Single listener method name must match class name")
def verify_actions(clazz):
@@ -308,7 +350,7 @@
if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower():
if not f.name.startswith("ACTION_"):
- error(clazz, f, "Intent action constant name must be ACTION_FOO")
+ error(clazz, f, "C3", "Intent action constant name must be ACTION_FOO")
else:
if clazz.fullname == "android.content.Intent":
prefix = "android.intent.action"
@@ -320,7 +362,7 @@
prefix = clazz.pkg.name + ".action"
expected = prefix + "." + f.name[7:]
if f.value != expected:
- error(clazz, f, "Inconsistent action value; expected %s" % (expected))
+ error(clazz, f, "C4", "Inconsistent action value; expected %s" % (expected))
def verify_extras(clazz):
@@ -340,7 +382,7 @@
if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
if "_EXTRA" in f.name or "EXTRA_" in f.name or ".extra" in f.value.lower():
if not f.name.startswith("EXTRA_"):
- error(clazz, f, "Intent extra must be EXTRA_FOO")
+ error(clazz, f, "C3", "Intent extra must be EXTRA_FOO")
else:
if clazz.pkg.name == "android.content" and clazz.name == "Intent":
prefix = "android.intent.extra"
@@ -350,7 +392,7 @@
prefix = clazz.pkg.name + ".extra"
expected = prefix + "." + f.name[6:]
if f.value != expected:
- error(clazz, f, "Inconsistent extra value; expected %s" % (expected))
+ error(clazz, f, "C4", "Inconsistent extra value; expected %s" % (expected))
def verify_equals(clazz):
@@ -359,7 +401,7 @@
eq = "equals" in methods
hc = "hashCode" in methods
if eq != hc:
- error(clazz, None, "Must override both equals and hashCode; missing one")
+ error(clazz, None, "M8", "Must override both equals and hashCode; missing one")
def verify_parcelable(clazz):
@@ -370,17 +412,17 @@
describe = [ i for i in clazz.methods if i.name == "describeContents" ]
if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
- error(clazz, None, "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
+ error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
def verify_protected(clazz):
- """Verify that no protected methods are allowed."""
+ """Verify that no protected methods or fields are allowed."""
for m in clazz.methods:
if "protected" in m.split:
- error(clazz, m, "No protected methods; must be public")
+ error(clazz, m, "M7", "Protected methods not allowed; must be public")
for f in clazz.fields:
if "protected" in f.split:
- error(clazz, f, "No protected fields; must be public")
+ error(clazz, f, "M7", "Protected fields not allowed; must be public")
def verify_fields(clazz):
@@ -410,18 +452,18 @@
elif clazz.fullname.startswith("android.util.Mutable"):
pass
else:
- error(clazz, f, "Bare fields must be marked final; consider adding accessors")
+ error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable")
if not "static" in f.split:
if not re.match("[a-z]([a-zA-Z]+)?", f.name):
- error(clazz, f, "Non-static fields must be named with myField style")
+ error(clazz, f, "S1", "Non-static fields must be named using myField style")
if re.match("[ms][A-Z]", f.name):
- error(clazz, f, "Don't expose your internal objects")
+ error(clazz, f, "F1", "Internal objects must not be exposed")
if re.match("[A-Z_]+", f.name):
if "static" not in f.split or "final" not in f.split:
- error(clazz, f, "Constants must be marked static final")
+ error(clazz, f, "C2", "Constants must be marked static final")
def verify_register(clazz):
@@ -434,34 +476,34 @@
if m.name.startswith("register"):
other = "unregister" + m.name[8:]
if other not in methods:
- error(clazz, m, "Missing unregister method")
+ error(clazz, m, "L2", "Missing unregister method")
if m.name.startswith("unregister"):
other = "register" + m.name[10:]
if other not in methods:
- error(clazz, m, "Missing register method")
+ error(clazz, m, "L2", "Missing register method")
if m.name.startswith("add") or m.name.startswith("remove"):
- error(clazz, m, "Callback methods should be named register/unregister")
+ error(clazz, m, "L3", "Callback methods should be named register/unregister")
if "Listener" in m.raw:
if m.name.startswith("add"):
other = "remove" + m.name[3:]
if other not in methods:
- error(clazz, m, "Missing remove method")
+ error(clazz, m, "L2", "Missing remove method")
if m.name.startswith("remove") and not m.name.startswith("removeAll"):
other = "add" + m.name[6:]
if other not in methods:
- error(clazz, m, "Missing add method")
+ error(clazz, m, "L2", "Missing add method")
if m.name.startswith("register") or m.name.startswith("unregister"):
- error(clazz, m, "Listener methods should be named add/remove")
+ error(clazz, m, "L3", "Listener methods should be named add/remove")
def verify_sync(clazz):
"""Verify synchronized methods aren't exposed."""
for m in clazz.methods:
if "synchronized" in m.split:
- error(clazz, m, "Internal lock exposed")
+ error(clazz, m, "M5", "Internal locks must not be exposed")
def verify_intent_builder(clazz):
@@ -473,7 +515,7 @@
if m.name.startswith("create") and m.name.endswith("Intent"):
pass
else:
- error(clazz, m, "Methods creating an Intent should be named createFooIntent()")
+ error(clazz, m, "FW1", "Methods creating an Intent must be named createFooIntent()")
def verify_helper_classes(clazz):
@@ -483,57 +525,45 @@
if "extends android.app.Service" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Service"):
- error(clazz, None, "Inconsistent class name; should be FooService")
+ error(clazz, None, "CL4", "Inconsistent class name; should be FooService")
found = False
for f in clazz.fields:
if f.name == "SERVICE_INTERFACE":
found = True
if f.value != clazz.fullname:
- error(clazz, f, "Inconsistent interface constant; expected %s" % (clazz.fullname))
-
- if not found:
- warn(clazz, None, "Missing SERVICE_INTERFACE constant")
-
- if "abstract" in clazz.split and not clazz.fullname.startswith("android.service."):
- warn(clazz, None, "Services extended by developers should be under android.service")
+ error(clazz, f, "C4", "Inconsistent interface constant; expected %s" % (clazz.fullname))
if "extends android.content.ContentProvider" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Provider"):
- error(clazz, None, "Inconsistent class name; should be FooProvider")
+ error(clazz, None, "CL4", "Inconsistent class name; should be FooProvider")
found = False
for f in clazz.fields:
if f.name == "PROVIDER_INTERFACE":
found = True
if f.value != clazz.fullname:
- error(clazz, f, "Inconsistent interface name; expected %s" % (clazz.fullname))
-
- if not found:
- warn(clazz, None, "Missing PROVIDER_INTERFACE constant")
-
- if "abstract" in clazz.split and not clazz.fullname.startswith("android.provider."):
- warn(clazz, None, "Providers extended by developers should be under android.provider")
+ error(clazz, f, "C4", "Inconsistent interface constant; expected %s" % (clazz.fullname))
if "extends android.content.BroadcastReceiver" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Receiver"):
- error(clazz, None, "Inconsistent class name; should be FooReceiver")
+ error(clazz, None, "CL4", "Inconsistent class name; should be FooReceiver")
if "extends android.app.Activity" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Activity"):
- error(clazz, None, "Inconsistent class name; should be FooActivity")
+ error(clazz, None, "CL4", "Inconsistent class name; should be FooActivity")
if test_methods:
for m in clazz.methods:
if "final" in m.split: continue
if not re.match("on[A-Z]", m.name):
if "abstract" in m.split:
- error(clazz, m, "Methods implemented by developers must be named onFoo()")
+ warn(clazz, m, None, "Methods implemented by developers should be named onFoo()")
else:
- warn(clazz, m, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
+ warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
def verify_builder(clazz):
@@ -543,7 +573,7 @@
if not clazz.name.endswith("Builder"): return
if clazz.name != "Builder":
- warn(clazz, None, "Builder should be defined as inner class")
+ warn(clazz, None, None, "Builder should be defined as inner class")
has_build = False
for m in clazz.methods:
@@ -555,26 +585,26 @@
if m.name.startswith("clear"): continue
if m.name.startswith("with"):
- error(clazz, m, "Builder methods names must follow setFoo() style")
+ warn(clazz, m, None, "Builder methods names should use setFoo() style")
if m.name.startswith("set"):
if not m.typ.endswith(clazz.fullname):
- warn(clazz, m, "Methods should return the builder")
+ warn(clazz, m, "M4", "Methods must return the builder object")
if not has_build:
- warn(clazz, None, "Missing build() method")
+ warn(clazz, None, None, "Missing build() method")
def verify_aidl(clazz):
"""Catch people exposing raw AIDL."""
if "extends android.os.Binder" in clazz.raw or "implements android.os.IInterface" in clazz.raw:
- error(clazz, None, "Exposing raw AIDL interface")
+ error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
def verify_internal(clazz):
"""Catch people exposing internal classes."""
if clazz.pkg.name.startswith("com.android"):
- error(clazz, None, "Exposing internal class")
+ error(clazz, None, None, "Internal classes must not be exposed")
def verify_layering(clazz):
@@ -609,38 +639,56 @@
for f in clazz.fields:
ir = rank(f.typ)
if ir and ir < cr:
- warn(clazz, f, "Field type violates package layering")
+ warn(clazz, f, "FW6", "Field type violates package layering")
for m in clazz.methods:
ir = rank(m.typ)
if ir and ir < cr:
- warn(clazz, m, "Method return type violates package layering")
+ warn(clazz, m, "FW6", "Method return type violates package layering")
for arg in m.args:
ir = rank(arg)
if ir and ir < cr:
- warn(clazz, m, "Method argument type violates package layering")
+ warn(clazz, m, "FW6", "Method argument type violates package layering")
-def verify_boolean(clazz, api):
- """Catches people returning boolean from getFoo() style methods.
- Ignores when matching setFoo() is present."""
+def verify_boolean(clazz):
+ """Verifies that boolean accessors are named correctly.
+ For example, hasFoo() and setHasFoo()."""
- methods = [ m.name for m in clazz.methods ]
+ def is_get(m): return len(m.args) == 0 and m.typ == "boolean"
+ def is_set(m): return len(m.args) == 1 and m.args[0] == "boolean"
- builder = clazz.fullname + ".Builder"
- builder_methods = []
- if builder in api:
- builder_methods = [ m.name for m in api[builder].methods ]
+ gets = [ m for m in clazz.methods if is_get(m) ]
+ sets = [ m for m in clazz.methods if is_set(m) ]
+
+ def error_if_exists(methods, trigger, expected, actual):
+ for m in methods:
+ if m.name == actual:
+ error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected))
for m in clazz.methods:
- if m.typ == "boolean" and m.name.startswith("get") and m.name != "get" and len(m.args) == 0:
- setter = "set" + m.name[3:]
- if setter in methods:
- pass
- elif builder is not None and setter in builder_methods:
- pass
- else:
- warn(clazz, m, "Methods returning boolean should be named isFoo, hasFoo, areFoo")
+ if is_get(m):
+ if re.match("is[A-Z]", m.name):
+ target = m.name[2:]
+ expected = "setIs" + target
+ error_if_exists(sets, m.name, expected, "setHas" + target)
+ elif re.match("has[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "setHas" + target
+ error_if_exists(sets, m.name, expected, "setIs" + target)
+ error_if_exists(sets, m.name, expected, "set" + target)
+ elif re.match("get[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "set" + target
+ error_if_exists(sets, m.name, expected, "setIs" + target)
+ error_if_exists(sets, m.name, expected, "setHas" + target)
+
+ if is_set(m):
+ if re.match("set[A-Z]", m.name):
+ target = m.name[3:]
+ expected = "get" + target
+ error_if_exists(sets, m.name, expected, "is" + target)
+ error_if_exists(sets, m.name, expected, "has" + target)
def verify_collections(clazz):
@@ -651,10 +699,10 @@
"java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
for m in clazz.methods:
if m.typ in bad:
- error(clazz, m, "Return type is concrete collection; should be interface")
+ error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface")
for arg in m.args:
if arg in bad:
- error(clazz, m, "Argument is concrete collection; should be interface")
+ error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
def verify_flags(clazz):
@@ -669,49 +717,291 @@
scope = f.name[0:f.name.index("FLAG_")]
if val & known[scope]:
- warn(clazz, f, "Found overlapping flag constant value")
+ warn(clazz, f, "C1", "Found overlapping flag constant value")
known[scope] |= val
-def verify_style(api):
- """Find all style issues in the given API level."""
- global failures
+def verify_exception(clazz):
+ """Verifies that methods don't throw generic exceptions."""
+ for m in clazz.methods:
+ if "throws java.lang.Exception" in m.raw or "throws java.lang.Throwable" in m.raw or "throws java.lang.Error" in m.raw:
+ error(clazz, m, "S1", "Methods must not throw generic exceptions")
+
+def verify_google(clazz):
+ """Verifies that APIs never reference Google."""
+
+ if re.search("google", clazz.raw, re.IGNORECASE):
+ error(clazz, None, None, "Must never reference Google")
+
+ test = []
+ test.extend(clazz.ctors)
+ test.extend(clazz.fields)
+ test.extend(clazz.methods)
+
+ for t in test:
+ if re.search("google", t.raw, re.IGNORECASE):
+ error(clazz, t, None, "Must never reference Google")
+
+
+def verify_bitset(clazz):
+ """Verifies that we avoid using heavy BitSet."""
+
+ for f in clazz.fields:
+ if f.typ == "java.util.BitSet":
+ error(clazz, f, None, "Field type must not be heavy BitSet")
+
+ for m in clazz.methods:
+ if m.typ == "java.util.BitSet":
+ error(clazz, m, None, "Return type must not be heavy BitSet")
+ for arg in m.args:
+ if arg == "java.util.BitSet":
+ error(clazz, m, None, "Argument type must not be heavy BitSet")
+
+
+def verify_manager(clazz):
+ """Verifies that FooManager is only obtained from Context."""
+
+ if not clazz.name.endswith("Manager"): return
+
+ for c in clazz.ctors:
+ error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors")
+
+
+def verify_boxed(clazz):
+ """Verifies that methods avoid boxed primitives."""
+
+ boxed = ["java.lang.Number","java.lang.Byte","java.lang.Double","java.lang.Float","java.lang.Integer","java.lang.Long","java.lang.Short"]
+
+ for c in clazz.ctors:
+ for arg in c.args:
+ if arg in boxed:
+ error(clazz, c, "M11", "Must avoid boxed primitives")
+
+ for f in clazz.fields:
+ if f.typ in boxed:
+ error(clazz, f, "M11", "Must avoid boxed primitives")
+
+ for m in clazz.methods:
+ if m.typ in boxed:
+ error(clazz, m, "M11", "Must avoid boxed primitives")
+ for arg in m.args:
+ if arg in boxed:
+ error(clazz, m, "M11", "Must avoid boxed primitives")
+
+
+def verify_static_utils(clazz):
+ """Verifies that helper classes can't be constructed."""
+ if clazz.fullname.startswith("android.opengl"): return
+ if re.match("android\.R\.[a-z]+", clazz.fullname): return
+
+ if len(clazz.fields) > 0: return
+ if len(clazz.methods) == 0: return
+
+ for m in clazz.methods:
+ if "static" not in m.split:
+ return
+
+ # At this point, we have no fields, and all methods are static
+ if len(clazz.ctors) > 0:
+ error(clazz, None, None, "Fully-static utility classes must not have constructor")
+
+
+def verify_overload_args(clazz):
+ """Verifies that method overloads add new arguments at the end."""
+ if clazz.fullname.startswith("android.opengl"): return
+
+ overloads = collections.defaultdict(list)
+ for m in clazz.methods:
+ if "deprecated" in m.split: continue
+ overloads[m.name].append(m)
+
+ for name, methods in overloads.items():
+ if len(methods) <= 1: continue
+
+ # Look for arguments common across all overloads
+ def cluster(args):
+ count = collections.defaultdict(int)
+ res = set()
+ for i in range(len(args)):
+ a = args[i]
+ res.add("%s#%d" % (a, count[a]))
+ count[a] += 1
+ return res
+
+ common_args = cluster(methods[0].args)
+ for m in methods:
+ common_args = common_args & cluster(m.args)
+
+ if len(common_args) == 0: continue
+
+ # Require that all common arguments are present at start of signature
+ locked_sig = None
+ for m in methods:
+ sig = m.args[0:len(common_args)]
+ if not common_args.issubset(cluster(sig)):
+ warn(clazz, m, "M2", "Expected common arguments [%s] at beginning of overloaded method" % (", ".join(common_args)))
+ elif not locked_sig:
+ locked_sig = sig
+ elif locked_sig != sig:
+ error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig)))
+
+
+def verify_callback_handlers(clazz):
+ """Verifies that methods adding listener/callback have overload
+ for specifying delivery thread."""
+
+ # Ignore UI packages which assume main thread
+ skip = [
+ "animation",
+ "view",
+ "graphics",
+ "transition",
+ "widget",
+ "webkit",
+ ]
+ for s in skip:
+ if s in clazz.pkg.name_path: return
+ if s in clazz.extends_path: return
+
+ # Ignore UI classes which assume main thread
+ if "app" in clazz.pkg.name_path or "app" in clazz.extends_path:
+ for s in ["ActionBar","Dialog","Application","Activity","Fragment","Loader"]:
+ if s in clazz.fullname: return
+ if "content" in clazz.pkg.name_path or "content" in clazz.extends_path:
+ for s in ["Loader"]:
+ if s in clazz.fullname: return
+
+ found = {}
+ by_name = collections.defaultdict(list)
+ for m in clazz.methods:
+ if m.name.startswith("unregister"): continue
+ if m.name.startswith("remove"): continue
+ if re.match("on[A-Z]+", m.name): continue
+
+ by_name[m.name].append(m)
+
+ for a in m.args:
+ if a.endswith("Listener") or a.endswith("Callback") or a.endswith("Callbacks"):
+ found[m.name] = m
+
+ for f in found.values():
+ takes_handler = False
+ for m in by_name[f.name]:
+ if "android.os.Handler" in m.args:
+ takes_handler = True
+ if not takes_handler:
+ warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Handler")
+
+
+def verify_context_first(clazz):
+ """Verifies that methods accepting a Context keep it the first argument."""
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
+ if len(m.args) > 1 and m.args[0] != "android.content.Context":
+ if "android.content.Context" in m.args[1:]:
+ error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
+
+
+def verify_listener_last(clazz):
+ """Verifies that methods accepting a Listener or Callback keep them as last arguments."""
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
+ if "Listener" in m.name or "Callback" in m.name: continue
+ found = False
+ for a in m.args:
+ if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"):
+ found = True
+ elif found and a != "android.os.Handler":
+ warn(clazz, m, "M3", "Listeners should always be at end of argument list")
+
+
+def verify_resource_names(clazz):
+ """Verifies that resource names have consistent case."""
+ if not re.match("android\.R\.[a-z]+", clazz.fullname): return
+
+ # Resources defined by files are foo_bar_baz
+ if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
+ for f in clazz.fields:
+ if re.match("[a-z1-9_]+$", f.name): continue
+ error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
+
+ # Resources defined inside files are fooBarBaz
+ if clazz.name in ["array","attr","id","bool","fraction","integer"]:
+ for f in clazz.fields:
+ if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
+ if re.match("layout_[a-z][a-zA-Z1-9]*$", f.name): continue
+ if re.match("state_[a-z_]*$", f.name): continue
+
+ if re.match("[a-z][a-zA-Z1-9]*$", f.name): continue
+ error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style")
+
+ # Styles are FooBar_Baz
+ if clazz.name in ["style"]:
+ for f in clazz.fields:
+ if re.match("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*$", f.name): continue
+ error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
+
+
+def examine_clazz(clazz):
+ """Find all style issues in the given class."""
+ if clazz.pkg.name.startswith("java"): return
+ if clazz.pkg.name.startswith("junit"): return
+ if clazz.pkg.name.startswith("org.apache"): return
+ if clazz.pkg.name.startswith("org.xml"): return
+ if clazz.pkg.name.startswith("org.json"): return
+ if clazz.pkg.name.startswith("org.w3c"): return
+
+ verify_constants(clazz)
+ verify_enums(clazz)
+ verify_class_names(clazz)
+ verify_method_names(clazz)
+ verify_callbacks(clazz)
+ verify_listeners(clazz)
+ verify_actions(clazz)
+ verify_extras(clazz)
+ verify_equals(clazz)
+ verify_parcelable(clazz)
+ verify_protected(clazz)
+ verify_fields(clazz)
+ verify_register(clazz)
+ verify_sync(clazz)
+ verify_intent_builder(clazz)
+ verify_helper_classes(clazz)
+ verify_builder(clazz)
+ verify_aidl(clazz)
+ verify_internal(clazz)
+ verify_layering(clazz)
+ verify_boolean(clazz)
+ verify_collections(clazz)
+ verify_flags(clazz)
+ verify_exception(clazz)
+ verify_google(clazz)
+ verify_bitset(clazz)
+ verify_manager(clazz)
+ verify_boxed(clazz)
+ verify_static_utils(clazz)
+ verify_overload_args(clazz)
+ verify_callback_handlers(clazz)
+ verify_context_first(clazz)
+ verify_listener_last(clazz)
+ verify_resource_names(clazz)
+
+
+def examine_stream(stream):
+ """Find all style issues in the given API stream."""
+ global failures
+ failures = {}
+ _parse_stream(stream, examine_clazz)
+ return failures
+
+
+def examine_api(api):
+ """Find all style issues in the given parsed API."""
+ global failures
failures = {}
for key in sorted(api.keys()):
- clazz = api[key]
-
- if clazz.pkg.name.startswith("java"): continue
- if clazz.pkg.name.startswith("junit"): continue
- if clazz.pkg.name.startswith("org.apache"): continue
- if clazz.pkg.name.startswith("org.xml"): continue
- if clazz.pkg.name.startswith("org.json"): continue
- if clazz.pkg.name.startswith("org.w3c"): continue
-
- verify_constants(clazz)
- verify_enums(clazz)
- verify_class_names(clazz)
- verify_method_names(clazz)
- verify_callbacks(clazz)
- verify_listeners(clazz)
- verify_actions(clazz)
- verify_extras(clazz)
- verify_equals(clazz)
- verify_parcelable(clazz)
- verify_protected(clazz)
- verify_fields(clazz)
- verify_register(clazz)
- verify_sync(clazz)
- verify_intent_builder(clazz)
- verify_helper_classes(clazz)
- verify_builder(clazz)
- verify_aidl(clazz)
- verify_internal(clazz)
- verify_layering(clazz)
- verify_boolean(clazz, api)
- verify_collections(clazz)
- verify_flags(clazz)
-
+ examine_clazz(api[key])
return failures
@@ -749,49 +1039,52 @@
prev_clazz = prev[key]
if not class_exists(cur, prev_clazz):
- error(prev_clazz, None, "Class removed or incompatible change")
+ error(prev_clazz, None, None, "Class removed or incompatible change")
continue
cur_clazz = cur[key]
for test in prev_clazz.ctors:
if not ctor_exists(cur, cur_clazz, test):
- error(prev_clazz, prev_ctor, "Constructor removed or incompatible change")
+ error(prev_clazz, prev_ctor, None, "Constructor removed or incompatible change")
methods = all_methods(prev, prev_clazz)
for test in methods:
if not method_exists(cur, cur_clazz, test):
- error(prev_clazz, test, "Method removed or incompatible change")
+ error(prev_clazz, test, None, "Method removed or incompatible change")
for test in prev_clazz.fields:
if not field_exists(cur, cur_clazz, test):
- error(prev_clazz, test, "Field removed or incompatible change")
+ error(prev_clazz, test, None, "Field removed or incompatible change")
return failures
-cur = parse_api(sys.argv[1])
-cur_fail = verify_style(cur)
+if __name__ == "__main__":
+ with open(sys.argv[1]) as f:
+ cur_fail = examine_stream(f)
-if len(sys.argv) > 2:
- prev = parse_api(sys.argv[2])
- prev_fail = verify_style(prev)
+ if len(sys.argv) > 2:
+ with open(sys.argv[2]) as f:
+ prev_fail = examine_stream(f)
- # ignore errors from previous API level
- for p in prev_fail:
- if p in cur_fail:
- del cur_fail[p]
+ # ignore errors from previous API level
+ for p in prev_fail:
+ if p in cur_fail:
+ del cur_fail[p]
- # look for compatibility issues
- compat_fail = verify_compat(cur, prev)
+ """
+ # NOTE: disabled because of memory pressure
+ # look for compatibility issues
+ compat_fail = verify_compat(cur, prev)
- print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
- for f in sorted(compat_fail):
- print compat_fail[f]
+ print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
+ for f in sorted(compat_fail):
+ print compat_fail[f]
+ print
+ """
+
+ print "%s API style issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
+ for f in sorted(cur_fail):
+ print cur_fail[f]
print
-
-
-print "%s API style issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
-for f in sorted(cur_fail):
- print cur_fail[f]
- print
diff --git a/tools/layoutlib/.idea/codeStyleSettings.xml b/tools/layoutlib/.idea/codeStyleSettings.xml
index a04e440..1f08f09 100644
--- a/tools/layoutlib/.idea/codeStyleSettings.xml
+++ b/tools/layoutlib/.idea/codeStyleSettings.xml
@@ -5,7 +5,6 @@
<value>
<option name="FIELD_NAME_PREFIX" value="m" />
<option name="STATIC_FIELD_NAME_PREFIX" value="s" />
- <option name="USE_FQ_CLASS_NAMES_IN_JAVADOC" value="false" />
<option name="INSERT_INNER_CLASS_IMPORTS" value="true" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
@@ -34,6 +33,9 @@
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
<option name="WRAP_COMMENTS" value="true" />
+ <JavaCodeStyleSettings>
+ <option name="CLASS_NAMES_IN_JAVADOC" value="3" />
+ </JavaCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
diff --git a/tools/layoutlib/.idea/misc.xml b/tools/layoutlib/.idea/misc.xml
index fd63e6c..fa48f70 100644
--- a/tools/layoutlib/.idea/misc.xml
+++ b/tools/layoutlib/.idea/misc.xml
@@ -12,5 +12,4 @@
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
-</project>
-
+</project>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
index c41a4ee..2691e56 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java
@@ -16,12 +16,13 @@
package android.content.res;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.layoutlib.bridge.Bridge;
-import android.content.res.AssetManager;
-
public class BridgeAssetManager extends AssetManager {
+ private AssetRepository mAssetRepository;
+
/**
* This initializes the static field {@link AssetManager#sSystem} which is used
* by methods who get a global asset manager using {@link AssetManager#getSystem()}.
@@ -48,6 +49,14 @@
AssetManager.sSystem = null;
}
- private BridgeAssetManager() {
+ public void setAssetRepository(AssetRepository assetRepository) {
+ mAssetRepository = assetRepository;
+ }
+
+ public AssetRepository getAssetRepository() {
+ return mAssetRepository;
+ }
+
+ public BridgeAssetManager() {
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index ab79664..42de4ec 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -18,21 +18,28 @@
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.AssetManager;
+import android.content.res.BridgeAssetManager;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
@@ -56,10 +63,28 @@
public static final int BOLD_FONT_WEIGHT_DELTA = 300;
public static final int BOLD_FONT_WEIGHT = 700;
- // FONT_SUFFIX_ITALIC will always match FONT_SUFFIX_BOLDITALIC and hence it must be checked
- // separately.
private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
+ private static final String EXTENSION_OTF = ".otf";
+
+ private static final int CACHE_SIZE = 10;
+ // The cache has a drawback that if the font file changed after the font object was created,
+ // we will not update it.
+ private static final Map<String, FontInfo> sCache =
+ new LinkedHashMap<String, FontInfo>(CACHE_SIZE) {
+ @Override
+ protected boolean removeEldestEntry(Entry<String, FontInfo> eldest) {
+ return size() > CACHE_SIZE;
+ }
+
+ @Override
+ public FontInfo put(String key, FontInfo value) {
+ // renew this entry.
+ FontInfo removed = remove(key);
+ super.put(key, value);
+ return removed;
+ }
+ };
/**
* A class associating {@link Font} with its metadata.
@@ -194,7 +219,7 @@
try {
return Font.createFont(Font.TRUETYPE_FONT, f);
} catch (Exception e) {
- if (path.endsWith(".otf") && e instanceof FontFormatException) {
+ if (path.endsWith(EXTENSION_OTF) && e instanceof FontFormatException) {
// If we aren't able to load an Open Type font, don't log a warning just yet.
// We wait for a case where font is being used. Only then we try to log the
// warning.
@@ -281,8 +306,74 @@
@LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Typeface.createFromAsset is not supported.", null, null);
+ FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
+ ffd.mValid = true;
+ if (mgr == null) {
+ return false;
+ }
+ if (mgr instanceof BridgeAssetManager) {
+ InputStream fontStream = null;
+ try {
+ AssetRepository assetRepository = ((BridgeAssetManager) mgr).getAssetRepository();
+ if (assetRepository == null) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
+ null);
+ return false;
+ }
+ if (!assetRepository.isSupported()) {
+ // Don't log any warnings on unsupported IDEs.
+ return false;
+ }
+ // Check cache
+ FontInfo fontInfo = sCache.get(path);
+ if (fontInfo != null) {
+ // renew the font's lease.
+ sCache.put(path, fontInfo);
+ ffd.addFont(fontInfo);
+ return true;
+ }
+ fontStream = assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING);
+ if (fontStream == null) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
+ path);
+ return false;
+ }
+ Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
+ fontInfo = new FontInfo();
+ fontInfo.mFont = font;
+ fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT;
+ fontInfo.mIsItalic = font.isItalic();
+ ffd.addFont(fontInfo);
+ return true;
+ } catch (IOException e) {
+ Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Unable to load font " + path, e,
+ path);
+ } catch (FontFormatException e) {
+ if (path.endsWith(EXTENSION_OTF)) {
+ // otf fonts are not supported on the user's config (JRE version + OS)
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "OpenType fonts are not supported yet: " + path, null, path);
+ } else {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Unable to load font " + path, e, path);
+ }
+ } finally {
+ if (fontStream != null) {
+ try {
+ fontStream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ return false;
+ }
+ // This should never happen. AssetManager is a final class (from user's perspective), and
+ // we've replaced every creation of AssetManager with our implementation. We create an
+ // exception and log it, but continue with rest of the rendering, without loading this font.
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "You have found a bug in the rendering library. Please file a bug at b.android.com.",
+ new RuntimeException("Asset Manager is not an instance of BridgeAssetManager"),
+ null);
return false;
}
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 36102f1..7e4ff69 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -179,7 +179,7 @@
XmlPullParser parser = ParserFactory.create(f);
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
- parser, bridgeContext, false);
+ parser, bridgeContext, value.isFramework());
return inflate(bridgeParser, root);
} catch (Exception e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index d90271b..32305a0 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -215,6 +215,12 @@
}
@Override
+ public void overridePendingAppTransitionClipReveal(int startX, int startY,
+ int startWidth, int startHeight) throws RemoteException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
// TODO Auto-generated method stub
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index a6c00f7..3915046 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -71,8 +71,10 @@
int x = 0;
if (outline.mRect != null) {
Shadow s = getRectShadow(parent, canvas, child, outline);
- shadow = s.mShadow;
- x = -s.mShadowWidth;
+ if (s != null) {
+ shadow = s.mShadow;
+ x = -s.mShadowWidth;
+ }
} else if (outline.mPath != null) {
shadow = getPathShadow(child, outline, canvas);
}
@@ -132,6 +134,9 @@
private static BufferedImage getPathShadow(View child, Outline outline, Canvas canvas) {
Rect clipBounds = canvas.getClipBounds();
+ if (clipBounds.isEmpty()) {
+ return null;
+ }
BufferedImage image = new BufferedImage(clipBounds.width(), clipBounds.height(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 3441878..2f62b93 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -18,6 +18,7 @@
import android.os.IBinder;
import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -48,6 +49,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.content.res.BridgeAssetManager;
import android.content.res.BridgeResources;
import android.content.res.BridgeTypedArray;
import android.content.res.Configuration;
@@ -102,6 +104,7 @@
* used to populate the mViewKeyMap.
*/
private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<Object, Object>();
+ private final BridgeAssetManager mAssets;
private Resources mSystemResources;
private final Object mProjectKey;
private final DisplayMetrics mMetrics;
@@ -141,6 +144,7 @@
*/
public BridgeContext(Object projectKey, DisplayMetrics metrics,
RenderResources renderResources,
+ AssetRepository assets,
IProjectCallback projectCallback,
Configuration config,
int targetSdkVersion,
@@ -151,6 +155,8 @@
mRenderResources = renderResources;
mConfig = config;
+ mAssets = new BridgeAssetManager();
+ mAssets.setAssetRepository(assets);
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.targetSdkVersion = targetSdkVersion;
@@ -1088,9 +1094,8 @@
}
@Override
- public AssetManager getAssets() {
- // pass
- return null;
+ public BridgeAssetManager getAssets() {
+ return mAssets;
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 62a03e1..4289689 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -206,4 +206,9 @@
// pass for now.
return null;
}
+
+ @Override
+ public void pokeDrawLock(IBinder window) {
+ // pass for now.
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java
index e00ea6a..51a0104 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java
@@ -29,6 +29,8 @@
public static final SessionParams.Key<String> FLAG_KEY_ROOT_TAG =
new SessionParams.Key<String>("rootTag", String.class);
+ public static final SessionParams.Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING =
+ new SessionParams.Key<Boolean>("disableBitmapCaching", Boolean.class);
// Disallow instances.
private SessionParamsFlags() {}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index 3a0321a..c34f9b5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -35,6 +35,7 @@
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
+import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
@@ -615,8 +616,22 @@
return;
}
- int width = layer.getImage().getWidth();
- int height = layer.getImage().getHeight();
+ int width;
+ int height;
+ Rectangle clipBounds = originalGraphics.getClipBounds();
+ if (clipBounds != null) {
+ if (clipBounds.width == 0 || clipBounds.height == 0) {
+ // Clip is 0 so no need to paint anything.
+ return;
+ }
+ // If we have clipBounds available, use them as they will always be
+ // smaller than the full layer size.
+ width = clipBounds.width;
+ height = clipBounds.height;
+ } else {
+ width = layer.getImage().getWidth();
+ height = layer.getImage().getHeight();
+ }
// Create a temporary image to which the color filter will be applied.
BufferedImage image = new BufferedImage(width, height,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 60f5331..127cb72 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -35,7 +35,6 @@
import android.content.res.Configuration;
import android.os.HandlerThread_Delegate;
-import android.os.Looper;
import android.util.DisplayMetrics;
import android.view.ViewConfiguration_Accessor;
import android.view.inputmethod.InputMethodManager;
@@ -71,7 +70,7 @@
/**
* Creates a renderAction.
* <p>
- * This <b>must</b> be followed by a call to {@link RenderAction#init()}, which act as a
+ * This <b>must</b> be followed by a call to {@link RenderAction#init(long)}, which act as a
* call to {@link RenderAction#acquire(long)}
*
* @param params the RenderParams. This must be a copy that the action can keep
@@ -121,8 +120,8 @@
// build the context
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
- mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
- mParams.isRtlSupported());
+ mParams.getAssets(), mParams.getProjectCallback(), getConfiguration(),
+ mParams.getTargetSdkVersion(), mParams.isRtlSupported());
setUp();
@@ -139,7 +138,7 @@
* The preparation can fail if another rendering took too long and the timeout was elapsed.
*
* More than one call to this from the same thread will have no effect and will return
- * {@link Result#SUCCESS}.
+ * {@link Result.Status#SUCCESS}.
*
* After scene actions have taken place, only one call to {@link #release()} must be
* done.
@@ -173,7 +172,7 @@
* Acquire the lock so that the scene can be acted upon.
* <p>
* This returns null if the lock was just acquired, otherwise it returns
- * {@link Result#SUCCESS} if the lock already belonged to that thread, or another
+ * {@link Result.Status#SUCCESS} if the lock already belonged to that thread, or another
* instance (see {@link Result#getStatus()}) if an error occurred.
*
* @param timeout the time to wait if another rendering is happening.
@@ -184,11 +183,11 @@
*/
private Result acquireLock(long timeout) {
ReentrantLock lock = Bridge.getLock();
- if (lock.isHeldByCurrentThread() == false) {
+ if (!lock.isHeldByCurrentThread()) {
try {
boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
- if (acquired == false) {
+ if (!acquired) {
return ERROR_TIMEOUT.createResult();
}
} catch (InterruptedException e) {
@@ -308,7 +307,7 @@
*/
protected void checkLock() {
ReentrantLock lock = Bridge.getLock();
- if (lock.isHeldByCurrentThread() == false) {
+ if (!lock.isHeldByCurrentThread()) {
throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
}
if (sCurrentContext != mContext) {
@@ -347,6 +346,7 @@
config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
if (config.screenHeightDp < config.screenWidthDp) {
+ //noinspection SuspiciousNameCombination
config.smallestScreenWidthDp = config.screenHeightDp;
} else {
config.smallestScreenWidthDp = config.screenWidthDp;
@@ -367,6 +367,7 @@
config.orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
case SQUARE:
+ //noinspection deprecation
config.orientation = Configuration.ORIENTATION_SQUARE;
break;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 84ee914..875cc87 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -551,7 +551,14 @@
// draw the views
// create the BufferedImage into which the layout will be rendered.
boolean newImage = false;
- if (newRenderSize || mCanvas == null) {
+
+ // When disableBitmapCaching is true, we do not reuse mImage and
+ // we create a new one in every render.
+ // This is useful when mImage is just a wrapper of Graphics2D so
+ // it doesn't get cached.
+ boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag(
+ SessionParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
+ if (newRenderSize || mCanvas == null || disableBitmapCaching) {
if (params.getImageFactory() != null) {
mImage = params.getImageFactory().getImage(
mMeasuredScreenWidth,
@@ -578,8 +585,12 @@
Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
true /*isMutable*/, hardwareConfig.getDensity());
- // create a Canvas around the Android bitmap
- mCanvas = new Canvas(bitmap);
+ if (mCanvas == null) {
+ // create a Canvas around the Android bitmap
+ mCanvas = new Canvas(bitmap);
+ } else {
+ mCanvas.setBitmap(bitmap);
+ }
mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
}