Merge "Add null egl/gles stub support"
diff --git a/Android.mk b/Android.mk
index 44fdb77..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 \
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 a1cdc8d..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,6 +1710,7 @@
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
@@ -5476,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[]);
@@ -5525,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";
@@ -11795,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
}
@@ -11845,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();
@@ -11864,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);
@@ -11880,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);
@@ -11944,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[]);
@@ -11991,17 +12002,9 @@
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 {
@@ -12014,6 +12017,12 @@
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();
@@ -12026,9 +12035,17 @@
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);
@@ -12081,41 +12098,24 @@
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 {
diff --git a/api/system-current.txt b/api/system-current.txt
index 13a8981..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,6 +1786,7 @@
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
@@ -5576,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[]);
@@ -5626,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";
@@ -12069,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
}
@@ -12119,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();
@@ -12138,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);
@@ -12154,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);
@@ -12218,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[]);
@@ -12265,17 +12276,9 @@
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 {
@@ -12288,6 +12291,12 @@
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();
@@ -12300,9 +12309,17 @@
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);
@@ -12355,41 +12372,24 @@
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 {
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 62081ee..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) {
}
}
@@ -1857,6 +1843,8 @@
runTaskLock();
} else if (op.equals("resizeable")) {
runTaskResizeable();
+ } else if (op.equals("resize")) {
+ runTaskResize();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -1890,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));
@@ -1986,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/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/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 005b1d9..bb307bb 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2313,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();
@@ -5438,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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index db380ed..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;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c5f534c..bdcc312 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1244,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;
}
@@ -1310,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;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1f5a1a0..a7e9413 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -464,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)
@@ -808,4 +809,5 @@
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/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/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/content/Context.java b/core/java/android/content/Context.java
index eabe297..46ccc95 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2971,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/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/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/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index bb162153..adab9be 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -132,6 +132,19 @@
float requestedRefreshRate, boolean inTraversal);
/**
+ * Applies an offset to the contents of a display, for example to avoid burn-in.
+ * <p>
+ * TODO: Technically this should be associated with a physical rather than logical
+ * display but this is good enough for now.
+ * </p>
+ *
+ * @param displayId The logical display id to update.
+ * @param x The X offset by which to shift the contents of the display.
+ * @param y The Y offset by which to shift the contents of the display.
+ */
+ public abstract void setDisplayOffsets(int displayId, int x, int y);
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
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/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/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 0d80c0d..06666f4 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,6 +16,7 @@
package android.preference;
+import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.XmlRes;
import android.app.Fragment;
@@ -531,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
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/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/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index c1341e1..8e9eb48 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -78,7 +78,10 @@
/**
* Bit field indicating that street addresses should be matched in methods that
- * take an options mask
+ * take an options mask. Note that this uses the
+ * {@link android.webkit.WebView#findAddress(String) findAddress()} method in
+ * {@link android.webkit.WebView} for finding addresses, which has various
+ * limitations.
*/
public static final int MAP_ADDRESSES = 0x08;
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/PhoneWindow.java b/core/java/android/view/PhoneWindow.java
index c1498ec..0814101 100644
--- a/core/java/android/view/PhoneWindow.java
+++ b/core/java/android/view/PhoneWindow.java
@@ -1,4 +1,5 @@
/*
+ * 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.
@@ -2694,73 +2695,12 @@
if (mActionModeView != null) {
mActionModeView.killMode();
}
- ActionModeWrapper wrapperMode =
- new ActionModeWrapper(mContext, wrappedCallback);
+ ActionModeWrapper wrapperMode = new ActionModeWrapper(
+ mContext, wrappedCallback, new StandaloneActionModeProvider());
if (callback.onCreateActionMode(wrapperMode, wrapperMode.getMenu())) {
- if (wrapperMode.getType() == ActionMode.TYPE_PRIMARY) {
- 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) {
- wrapperMode.setActionModeView(mActionModeView);
- wrapperMode.setFocusable(mActionModePopup == null);
- wrapperMode.lockType();
- wrapperMode.invalidate();
- mActionModeView.initForMode(wrapperMode);
- mActionModeView.setVisibility(View.VISIBLE);
- mActionMode = wrapperMode;
- if (mActionModePopup != null) {
- post(mShowActionModePopup);
- }
- mActionModeView.sendAccessibilityEvent(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- }
- }
+ mActionMode = wrapperMode;
+ wrapperMode.lockType();
+ mActionMode.invalidate();
} else {
mActionMode = null;
}
@@ -3259,6 +3199,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 {
@@ -4156,12 +4172,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/View.java b/core/java/android/view/View.java
index f99d2d5..502d5ee 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,7 +16,9 @@
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;
@@ -32,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;
@@ -4326,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());
}
@@ -4362,8 +4359,7 @@
* content in this view is visible.
*/
public void setFadingEdgeLength(int length) {
- initScrollCache();
- mScrollCache.fadingEdgeLength = length;
+ getScrollCache().fadingEdgeLength = length;
}
/**
@@ -4467,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);
@@ -4478,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);
@@ -4539,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;
}
@@ -11571,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
@@ -11603,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()
@@ -11622,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
@@ -11642,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()
@@ -11664,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;
}
/**
@@ -12388,7 +12322,7 @@
public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
if (horizontalFadingEdgeEnabled) {
- initScrollCache();
+ getScrollCache();
}
mViewFlags ^= FADING_EDGE_HORIZONTAL;
@@ -12425,7 +12359,7 @@
public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
if (verticalFadingEdgeEnabled) {
- initScrollCache();
+ getScrollCache();
}
mViewFlags ^= FADING_EDGE_VERTICAL;
@@ -12565,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);
}
/**
@@ -12584,7 +12511,7 @@
* @attr ref android.R.styleable#View_fadeScrollbars
*/
public boolean isScrollbarFadingEnabled() {
- return mScrollCache != null && mScrollCache.fadeScrollBars;
+ return mScrollCache != null && mScrollCache.isFadingEnabled();
}
/**
@@ -12866,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);
}
}
@@ -15352,7 +15235,7 @@
canvas.saveLayer(right - length, top, right, bottom, null, flags);
}
} else {
- scrollabilityCache.setFadeColor(solidColor);
+ scrollabilityCache.setFadingEdgeColor(solidColor);
}
// Step 3, draw the content
@@ -15362,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);
@@ -20624,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/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f392682..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;
@@ -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();
}
}
@@ -3084,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;
@@ -3228,10 +3233,6 @@
mReportNextDraw = true;
}
- if (mView != null) {
- forceLayout(mView);
- }
-
requestLayout();
}
break;
@@ -3246,9 +3247,6 @@
mWinFrame.top = t;
mWinFrame.bottom = t + h;
- if (mView != null) {
- forceLayout(mView);
- }
requestLayout();
}
break;
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/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/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/Editor.java b/core/java/android/widget/Editor.java
index 8601d2b..1ba11da 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4199,6 +4199,13 @@
}
/**
+ * @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).
*/
@@ -4213,97 +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.
- // TODO: This sequence doesn't work right: a, left-arrow, b, undo, undo.
- // The two edits are incorrectly merged, so there is only one undo available.
- 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.
}
}
/**
* An operation to undo a single "edit" to a text view.
*/
- public static class TextModifyOperation extends UndoOperation<Editor> {
- int mRangeStart, mRangeEnd;
- CharSequence mOldText;
+ 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
@@ -4312,62 +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.
+ /**
+ * 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;
+ }
+ }
+
+ private boolean mergeInsertWith(EditOperation edit) {
+ if (DEBUG_UNDO) Log.d(TAG, "mergeInsertWith " + edit);
+ // Only merge continuous insertions.
+ if (edit.mType != TYPE_INSERT) {
+ return false;
+ }
+ // Only merge insertions that are contiguous.
+ if (getNewTextEnd() != edit.mNewTextStart) {
+ return false;
+ }
+ 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 editable = (Editable)editor.mTextView.getText();
- CharSequence curText;
- if (mRangeStart >= mRangeEnd) {
- curText = null;
- } else {
- curText = editable.subSequence(mRangeStart, mRangeEnd);
+ 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);
+ }
}
- if (DEBUG_UNDO) {
- Log.d(TAG, "Swap: range=(" + mRangeStart + "-" + mRangeEnd
- + "), oldText=" + mOldText);
- Log.d(TAG, "Swap: curText=" + curText);
+ // Restore the cursor position.
+ // TODO: Select all the text that was undone.
+ if (newCursorPos <= text.length()) {
+ Selection.setSelection(text, newCursorPos);
}
- if (mOldText == null) {
- editable.delete(mRangeStart, mRangeEnd);
- mRangeEnd = mRangeStart;
- } else {
- editable.replace(mRangeStart, mRangeEnd, mOldText);
- mRangeEnd = mRangeStart + mOldText.length();
- }
- mOldText = curText;
}
@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 static final Parcelable.ClassLoaderCreator<EditOperation> CREATOR
+ = new Parcelable.ClassLoaderCreator<EditOperation>() {
@Override
- public TextModifyOperation createFromParcel(Parcel in) {
- return new TextModifyOperation(in, null);
+ public EditOperation createFromParcel(Parcel in) {
+ return new EditOperation(in, null);
}
@Override
- public TextModifyOperation createFromParcel(Parcel in, ClassLoader loader) {
- return new TextModifyOperation(in, loader);
+ public EditOperation createFromParcel(Parcel in, ClassLoader loader) {
+ return new EditOperation(in, loader);
}
@Override
- public TextModifyOperation[] newArray(int size) {
- return new TextModifyOperation[size];
+ public EditOperation[] newArray(int size) {
+ return new EditOperation[size];
}
};
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 406a274..03878fc 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -401,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) {
@@ -1648,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 {
@@ -1680,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
@@ -1703,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/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/TextView.java b/core/java/android/widget/TextView.java
index 9297731..2d0a9cb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8412,6 +8412,10 @@
return onTextContextMenuItem(ID_REDO);
}
break;
+ case KeyEvent.KEYCODE_V:
+ if (canPaste()) {
+ return onTextContextMenuItem(ID_PASTE_AS_PLAIN_TEXT);
+ }
}
}
return super.onKeyShortcut(keyCode, event);
@@ -8794,6 +8798,7 @@
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
@@ -8834,7 +8839,11 @@
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:
@@ -9018,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);
@@ -9705,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/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 9ae9fa7..9aa36d3 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -411,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) {
@@ -420,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;
}
}
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/view/ActionModeWrapper.java b/core/java/com/android/internal/view/ActionModeWrapper.java
index ef1981a..72066b9 100644
--- a/core/java/com/android/internal/view/ActionModeWrapper.java
+++ b/core/java/com/android/internal/view/ActionModeWrapper.java
@@ -24,7 +24,6 @@
import android.view.View;
import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.widget.ActionBarContextView;
/**
* ActionMode implementation that wraps several actions modes and creates them on the fly depending
@@ -32,6 +31,22 @@
*/
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;
@@ -41,16 +56,16 @@
private CharSequence mTitle;
private CharSequence mSubtitle;
private View mCustomView;
+
+ private final ActionModeProvider mActionModeProvider;
- // Fields for StandaloneActionMode
- private ActionBarContextView mActionModeView;
- private boolean mIsFocusable;
-
- public ActionModeWrapper(Context context, ActionMode.Callback callback) {
+ 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
@@ -107,9 +122,7 @@
switch (getType()) {
case ActionMode.TYPE_PRIMARY:
default:
- mActionMode = new StandaloneActionMode(
- mActionModeView.getContext(),
- mActionModeView, mCallback, mIsFocusable, mMenu);
+ mActionMode = mActionModeProvider.createActionMode(mCallback, mMenu);
break;
case ActionMode.TYPE_FLOATING:
// Not implemented yet.
@@ -189,12 +202,4 @@
return new MenuInflater(mContext);
}
- public void setActionModeView(ActionBarContextView actionModeView) {
- mActionModeView = actionModeView;
- }
-
- public void setFocusable(boolean focusable) {
- mIsFocusable = focusable;
- }
-
}
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/jni/Android.mk b/core/jni/Android.mk
index 1dd10e1..28f1a3a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -5,7 +5,7 @@
LOCAL_CFLAGS += -DHAVE_CONFIG_H -DKHTML_NO_EXCEPTIONS -DGKWQ_NO_JAVA
LOCAL_CFLAGS += -DNO_SUPPORT_JS_BINDING -DQT_NO_WHEELEVENT -DKHTML_NO_XBL
LOCAL_CFLAGS += -U__APPLE__
-LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
+LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-non-virtual-dtor
LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
LOCAL_CPPFLAGS += -Wno-conversion-null
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 1afcf73..36f7963 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -160,7 +160,8 @@
android_eglGetDisplayInt
(JNIEnv *_env, jobject _this, jint display_id) {
- if ((EGLNativeDisplayType)display_id != EGL_DEFAULT_DISPLAY) {
+ if (static_cast<uintptr_t>(display_id) !=
+ reinterpret_cast<uintptr_t>(EGL_DEFAULT_DISPLAY)) {
jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglGetDisplay");
return 0;
}
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 713fff9..226162d 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -1935,7 +1935,11 @@
(GLsizei *)length,
(GLint *)size,
(GLenum *)type,
- (char *)name
+ // The cast below is incorrect. The driver will end up writing to the
+ // address specified by name, which will always crash the process since
+ // it is guaranteed to be in low memory. The additional static_cast
+ // suppresses the warning for now. http://b/19478262
+ (char *)static_cast<uintptr_t>(name)
);
if (_typeArray) {
releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -3643,7 +3647,7 @@
(GLenum)mode,
(GLsizei)count,
(GLenum)type,
- (GLvoid *)indicesOffset,
+ (GLvoid *)static_cast<uintptr_t>(indicesOffset),
(GLsizei)instanceCount
);
}
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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6094fd1..4b97138 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -300,6 +300,8 @@
<protected-broadcast android:name="android.intent.action.ACTION_SET_RADIO_CAPABILITY_DONE" />
<protected-broadcast android:name="android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED" />
+ <protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
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/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/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 d87e672..a33f8af 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 00bcfc9..a8dea11 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 8d7320a..43355520 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -58,16 +58,16 @@
<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" 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>
+ <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>
@@ -307,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>
@@ -579,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>
@@ -975,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>
@@ -992,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>
@@ -1347,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>
@@ -1383,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>
@@ -1651,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>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a7738e1..ce2aa9a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f332b7f..4afa0a3 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c190ae50..63365bb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ce725dd..3c75764 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 720a9a6..733b7a7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index edfb9ae..c246c242 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7860b26..7e12895 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e59b3f3..dcbc375 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e59b3f3..dcbc375 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 8d1a73e..e916cb6 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 04ed063..60a543f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index eb184be..fe077c8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 4334ae0..0b24d08 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -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>
@@ -1355,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>
@@ -1604,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>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2324981..2e040e33 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 74e6395..ce9d6ee 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0c3a606..aa10dd6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 648d241..0c7e7ba 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index d1526b0..babbb67 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8223cb2..1f0381b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1355,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>
@@ -1696,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>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4a17d54..fbb9160 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1362,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>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 17137a8..5a929bd 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index cf2f808..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>
@@ -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>
@@ -1355,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>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 3d73d74..4dc7d62 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index ac7eb10..6f8bd07 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1d1636d..c6b18e8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 10129f5..21ae52a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f97591d..2efd676 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index f1b4b13..a7fac00 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 3c3ba29..02fcd62 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 0ba2df4..491688c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1357,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>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 6310175..92aa838 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 227f982..027f994 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 1d33dfc..dfb23a3 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1782,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>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 8667ea1..fa546f2 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 27a984d..590e9ea 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index a756684..e6a27a1 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1362,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>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index cc24445..5f89553 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index fbc39a3..d9286eb 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 08c00d4..017cf95 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index f61cca0..7ce0974 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 2a36dc1..31f5fab 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 7b0e424..ef52827 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index daadd35..16cd07a 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index a62032d..b705d62 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1361,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>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9dc88ab..6be8c88 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6962938..04d4d09 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 8c7b472..8b3511e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8ad021b..acc9d41 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 43b5614..f1a11af 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1362,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>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a17c338..94bc21f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index e99cf51..51493d1 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1357,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>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 252a00e..85ece4f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1280,7 +1280,7 @@
<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" formatted="false" msgid="7900333017752027322">
<item quantity="few">K dispozícii sú siete Wi-Fi</item>
@@ -1369,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>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index eb101d3..320e17a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index d7c35b8..26a436a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1362,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>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 72d5b58..1457940 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index e81efee..f135f7a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index b1f87c6..07336d4 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 3ca3a6b..1767ce2 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 40d1999..230e915 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 4256fbb..98eec08 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0fe8006..3489298 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -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>
@@ -1355,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>
@@ -1614,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>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 3e835c0..bb48a43 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1369,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>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 12aeb95..d107b09 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 2b90194..c69a4ee 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index e608fb6..c19278e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 62f2219..c76ff7f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index e4c5a62..453043a 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5544324..b551b5f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index ef513ca..ea19554 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1355,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>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bc20378..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. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 51c6a66..fd8b803 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1852,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
@@ -2068,4 +2074,23 @@
<!-- 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>
+
+ <!-- If true, the display will be shifted around in ambient mode. -->
+ <bool name="config_enableBurnInProtection">false</bool>
+
+ <!-- Specifies the maximum burn-in offset displacement from the center. If -1, no maximum value
+ will be used. -->
+ <integer name="config_burnInProtectionMaxRadius">-1</integer>
+
+ <!-- Specifies the minimum burn-in offset horizontally. -->
+ <integer name="config_burnInProtectionMinHorizontalOffset">0</integer>
+
+ <!-- Specifies the maximum burn-in offset horizontally. -->
+ <integer name="config_burnInProtectionMaxHorizontalOffset">0</integer>
+
+ <!-- Specifies the minimum burn-in offset vertically. -->
+ <integer name="config_burnInProtectionMinVerticalOffset">0</integer>
+
+ <!-- Specifies the maximum burn-in offset vertically. -->
+ <integer name="config_burnInProtectionMaxVerticalOffset">0</integer>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index bec224e..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 -->
@@ -357,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 0e2c480..b84249a 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -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 1f4d37c..b6e79ad 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -91,4 +91,5 @@
<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 8814138..af4922f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2614,6 +2614,7 @@
<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" />
@@ -2638,5 +2639,8 @@
<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 ff03ca9..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. -->
@@ -3909,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 -->
@@ -5071,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 c618707..d75e496 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -653,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>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b414634..39c0e8f 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -254,6 +254,7 @@
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
<java-symbol type="bool" name="config_enable_puk_unlock_screen" />
+ <java-symbol type="bool" name="config_enableBurnInProtection" />
<java-symbol type="bool" name="config_hotswapCapable" />
<java-symbol type="bool" name="config_mms_content_disposition_support" />
<java-symbol type="bool" name="config_networkSamplingWakesDevice" />
@@ -344,7 +345,13 @@
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
<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_burnInProtectionMinHorizontalOffset" />
+ <java-symbol type="integer" name="config_burnInProtectionMaxHorizontalOffset" />
+ <java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" />
+ <java-symbol type="integer" name="config_burnInProtectionMaxVerticalOffset" />
+ <java-symbol type="integer" name="config_burnInProtectionMaxRadius" />
<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" />
@@ -753,7 +760,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" />
@@ -764,6 +773,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" />
@@ -1750,6 +1760,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" />
@@ -1996,15 +2007,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" />
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/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index 86021e5..a50fb54 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -554,13 +554,11 @@
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
- // TODO: This should be true but the current behavior is broken.
- assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
- // TODO: This should be true but the current behavior is broken.
- assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
+ assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
}
}
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/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.jd b/docs/html/distribute/tools/promote/device-art.jd
index f583eb9..814177b 100644
--- a/docs/html/distribute/tools/promote/device-art.jd
+++ b/docs/html/distribute/tools/promote/device-art.jd
@@ -417,7 +417,7 @@
}
if (this.archived) {
- deviceList = '.device-list.archived';
+ deviceList = '.device-list.archive';
} else if (this.hidden) {
deviceList = '.device-list.hidden';
}
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/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/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/installing/index.jd b/docs/html/sdk/installing/index.jd
index d899ef3..45d1890 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -124,7 +124,7 @@
<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
+ lib32ncurses5-dev, and lib32stdc++6 packages. These packages are required to support 32-bit apps
on a 64-bit machine. </p>
</li>
</ol>
diff --git a/docs/html/tools/help/android.jd b/docs/html/tools/help/android.jd
index 19891e8..0d7d2aa 100644
--- a/docs/html/tools/help/android.jd
+++ b/docs/html/tools/help/android.jd
@@ -6,25 +6,26 @@
<p>{@code android} is an important development tool that lets you:</p>
<ul>
- <li>Create, delete, and view Android Virtual Devices (AVDs). See <a href=
- "{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the Command
-Line</a>.</li>
+ <li>Create, delete, and view Android Virtual Devices (AVDs). See <a href=
+ "{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the Command Line</a>.</li>
- <li>Create and update Android projects. See <a href=
+ <li>Create and update Android projects. See <a href=
"{@docRoot}tools/projects/projects-cmdline.html">Managing Projects from
the Command Line</a>.</li>
- <li>Update your Android SDK with new platforms, add-ons, and documentation. See <a href=
- "{@docRoot}sdk/exploring.html">Exploring the SDK</a>.</li>
- </ul>If you are using Eclipse, the <code>android</code> tool's features are integrated
- into ADT, so you should not need to use this tool directly.
-
+ <li>Update your Android SDK with new platforms, add-ons, and documentation. See <a href=
+ "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>.</li>
+ </ul>
+
+<p>If you are using Android Studio or Eclipse, the <code>android</code> tool's features are
+integrated into the IDE, so you should not need to use this tool directly. </p>
+
<p class="note"><strong>Note:</strong> The documentation of options below is not exhaustive
and may be out of date. For the most current list of options, execute <code>android
--help</code>.</p>
-
-
-
+
+
+
<h2>Syntax</h2>
<pre>android [global options] action [action options]</pre>
diff --git a/docs/html/tools/revisions/gradle-plugin.jd b/docs/html/tools/revisions/gradle-plugin.jd
index 23170e1..ebca5c7 100644
--- a/docs/html/tools/revisions/gradle-plugin.jd
+++ b/docs/html/tools/revisions/gradle-plugin.jd
@@ -40,7 +40,7 @@
<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</a> <em>(February 2015)</em>
+ alt=""/>Android Plugin for Gradle, Revision 1.1.0</a> <em>(February 2015)</em>
</p>
<div class="toggle-content-toggleme">
@@ -58,25 +58,59 @@
<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 debugging issue when displaying method input parameters at breakpoints.
- (<a href="http://b.android.com/82031">Issue 82031</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>
+ <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</a> <em>(December 2014)</em>
+ alt=""/>Android Plugin for Gradle, Revision 1.0.1</a> <em>(January 2015)</em>
</p>
<div class="toggle-content-toggleme">
@@ -86,7 +120,51 @@
<dd>
<ul>
- <li>Gradle 2.2.1 or higher.</li>
+ <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>
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index 9e7721b..1860feb 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -96,10 +96,9 @@
<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>Android Studio Project and Directory Structure</h3>
@@ -182,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>
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/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/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/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 616aebd..f5353d4 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -558,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
@@ -574,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
*/
@@ -586,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
*/
@@ -656,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
@@ -671,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;
@@ -834,7 +971,6 @@
}
}
- /** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
if (mHotspotBounds != null) {
@@ -1230,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/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 556c59f..c6ea91d 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -614,7 +614,6 @@
onHotspotBoundsChanged();
}
- /** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
outRect.set(mHotspotBounds);
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/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/Caches.cpp b/libs/hwui/Caches.cpp
index 7ab7a6a..e5489a8 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -255,7 +255,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;
}
@@ -397,7 +397,7 @@
///////////////////////////////////////////////////////////////////////////////
void Caches::initTempProperties() {
- propertyLightDiameter = -1.0f;
+ propertyLightRadius = -1.0f;
propertyLightPosY = -1.0f;
propertyLightPosZ = -1.0f;
propertyAmbientRatio = -1.0f;
@@ -411,9 +411,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 5563937..8aea8ff 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -211,7 +211,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/FrameInfo.h b/libs/hwui/FrameInfo.h
index 3c31677..65daf03 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -28,7 +28,7 @@
#define UI_THREAD_FRAME_INFO_SIZE 9
-HWUI_ENUM(FrameInfoIndex,
+enum class FrameInfoIndex {
kFlags = 0,
kIntendedVsync,
kVsync,
@@ -47,13 +47,14 @@
// Must be the last value!
kNumIndexes
-);
+};
-HWUI_ENUM(FrameInfoFlags,
+enum class FrameInfoFlags {
kWindowLayoutChanged = 1 << 0,
kRTAnimation = 1 << 1,
kSurfaceCanvas = 1 << 2,
-);
+};
+MAKE_FLAGS_ENUM(FrameInfoFlags)
class ANDROID_API UiFrameInfoBuilder {
public:
@@ -62,17 +63,21 @@
}
UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
- mBuffer[FrameInfoIndex::kVsync] = vsyncTime;
- mBuffer[FrameInfoIndex::kIntendedVsync] = intendedVsync;
+ set(FrameInfoIndex::kVsync) = vsyncTime;
+ set(FrameInfoIndex::kIntendedVsync) = intendedVsync;
return *this;
}
- UiFrameInfoBuilder& addFlag(FrameInfoFlagsEnum flag) {
- mBuffer[FrameInfoIndex::kFlags] |= static_cast<uint64_t>(flag);
+ 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;
};
@@ -81,33 +86,37 @@
void importUiThreadInfo(int64_t* info);
void markSyncStart() {
- mFrameInfo[FrameInfoIndex::kSyncStart] = systemTime(CLOCK_MONOTONIC);
+ set(FrameInfoIndex::kSyncStart) = systemTime(CLOCK_MONOTONIC);
}
void markIssueDrawCommandsStart() {
- mFrameInfo[FrameInfoIndex::kIssueDrawCommandsStart] = systemTime(CLOCK_MONOTONIC);
+ set(FrameInfoIndex::kIssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
}
void markSwapBuffers() {
- mFrameInfo[FrameInfoIndex::kSwapBuffers] = systemTime(CLOCK_MONOTONIC);
+ set(FrameInfoIndex::kSwapBuffers) = systemTime(CLOCK_MONOTONIC);
}
void markFrameCompleted() {
- mFrameInfo[FrameInfoIndex::kFrameCompleted] = systemTime(CLOCK_MONOTONIC);
+ set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC);
}
- int64_t operator[](FrameInfoIndexEnum index) const {
+ 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 >= FrameInfoIndex::kNumIndexes) return 0;
- return mFrameInfo[static_cast<int>(index)];
+ if (index < 0 || index >= static_cast<int>(FrameInfoIndex::kNumIndexes)) return 0;
+ return mFrameInfo[index];
}
private:
- int64_t mFrameInfo[FrameInfoIndex::kNumIndexes];
+ inline int64_t& set(FrameInfoIndex index) {
+ return mFrameInfo[static_cast<int>(index)];
+ }
+
+ int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::kNumIndexes)];
};
} /* namespace uirenderer */
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index 6eca468..e500546 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -76,18 +76,20 @@
GLuint indexBufferObject;
const void* vertices;
const void* indices;
+ GLvoid* texCoordOffset;
int elementCount;
GLsizei stride;
- GLvoid* texCoordOffset;
TextureVertex mappedVertices[4];
} mesh;
struct Fill {
Program* program;
- Texture* texture;
- GLenum textureFilter;
- GLenum textureClamp;
+ struct TextureData {
+ Texture* texture;
+ GLenum filter;
+ GLenum clamp;
+ } texture;
bool colorEnabled;
FloatColor color;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index f133d42..4617588 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -73,8 +73,7 @@
return *this;
}
-GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper,
- bool isAlphaMaskTexture) {
+GlopBuilder& GlopBuilder::setMeshTexturedUnitQuad(const UvMapper* uvMapper) {
TRIGGER_STAGE(kMeshStage);
mOutGlop->mesh.vertexFlags = kTextureCoord_Attrib;
@@ -87,19 +86,18 @@
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;
- mOutGlop->mesh.texCoordOffset = (GLvoid*) kMeshTextureOffset;
-
mDescription.hasTexture = true;
- mDescription.hasAlpha8Texture = isAlphaMaskTexture;
return *this;
}
@@ -112,13 +110,29 @@
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;
- mOutGlop->mesh.texCoordOffset = nullptr;
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);
@@ -132,6 +146,7 @@
mOutGlop->mesh.vertices = vertexBuffer.getBuffer();
mOutGlop->mesh.indexBufferObject = 0;
mOutGlop->mesh.indices = vertexBuffer.getIndices();
+ mOutGlop->mesh.texCoordOffset = nullptr;
mOutGlop->mesh.elementCount = indices
? vertexBuffer.getIndexCount() : vertexBuffer.getVertexCount();
mOutGlop->mesh.stride = alphaVertex ? kAlphaVertexStride : kVertexStride;
@@ -168,7 +183,7 @@
mOutGlop->blend = { GL_ZERO, GL_ZERO };
if (mOutGlop->fill.color.a < 1.0f
|| (mOutGlop->mesh.vertexFlags & kAlpha_Attrib)
- || (mOutGlop->fill.texture && mOutGlop->fill.texture->blend)
+ || (mOutGlop->fill.texture.texture && mOutGlop->fill.texture.texture->blend)
|| mOutGlop->roundRectClipState
|| PaintUtils::isBlendedShader(shader)
|| PaintUtils::isBlendedColorFilter(colorFilter)
@@ -240,9 +255,7 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = &texture;
- mOutGlop->fill.textureFilter = PaintUtils::getFilter(paint);
- mOutGlop->fill.textureClamp = GL_CLAMP_TO_EDGE;
+ mOutGlop->fill.texture = { &texture, PaintUtils::getFilter(paint), GL_CLAMP_TO_EDGE };
if (paint) {
int color = paint->getColor();
@@ -270,6 +283,7 @@
}
}
+ mDescription.hasAlpha8Texture = isAlphaMaskTexture;
if (isAlphaMaskTexture) {
mDescription.modulate = mOutGlop->fill.color.isNotBlack();
} else {
@@ -282,9 +296,7 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = nullptr;
- mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
- mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+ mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM };
setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
paint.getShader(), paint.getColorFilter());
@@ -297,15 +309,13 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = &texture;
-
- //specify invalid, since these are always static for PathTextures
- mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
- mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+ //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;
}
@@ -315,11 +325,8 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = &texture;
-
- //specify invalid, since these are always static for ShadowTextures
- mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
- mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
+ //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;
@@ -331,6 +338,7 @@
setFill(shadowColor, alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
paint.getShader(), paint.getColorFilter());
+ mDescription.hasAlpha8Texture = true;
mDescription.modulate = mOutGlop->fill.color.isNotBlack();
return *this;
}
@@ -339,12 +347,8 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = nullptr;
- mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
- mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
-
+ mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM };
setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, nullptr, nullptr);
-
return *this;
}
@@ -352,19 +356,30 @@
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
- mOutGlop->fill.texture = nullptr;
- mOutGlop->fill.textureFilter = GL_INVALID_ENUM;
- mOutGlop->fill.textureClamp = GL_INVALID_ENUM;
-
+ 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::setTransformClip(const Matrix4& ortho,
+GlopBuilder& GlopBuilder::setTransform(const Matrix4& ortho,
const Matrix4& transform, bool fudgingOffset) {
TRIGGER_STAGE(kTransformStage);
@@ -396,12 +411,13 @@
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.textureFilter = GL_NEAREST;
+ mOutGlop->fill.texture.filter = GL_NEAREST;
}
mOutGlop->transform.modelView.loadTranslate(left, top, 0.0f);
@@ -419,6 +435,30 @@
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);
@@ -431,11 +471,17 @@
// 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);
// serialize shader info into ShaderData
- GLuint textureUnit = mOutGlop->fill.texture ? 1 : 0;
+ GLuint textureUnit = mOutGlop->fill.texture.texture ? 1 : 0;
SkiaShader::store(mCaches, mShader, mOutGlop->transform.modelView,
&textureUnit, &mDescription, &(mOutGlop->fill.skiaShaderData));
@@ -448,6 +494,8 @@
&& !mDescription.hasGradient
&& !mDescription.hasBitmap;
mOutGlop->fill.colorEnabled = mDescription.modulate || singleColor;
+
+ verify(mDescription, *mOutGlop);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 546e6c5..cbdd0cd 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -39,9 +39,10 @@
GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop);
GlopBuilder& setMeshUnitQuad();
- GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper, bool isAlphaMaskTexture);
+ 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,
@@ -52,12 +53,15 @@
const SkPaint& paint, float alphaScale);
GlopBuilder& setFillBlack();
GlopBuilder& setFillClear();
+ GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
+ float alpha, SkXfermode::Mode mode);
- GlopBuilder& setTransformClip(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
+ 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& setRoundRectClipState(const RoundRectClipState* roundRectClipState);
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
index 62cb97c..d0ea3a6 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -30,8 +30,8 @@
};
struct Comparison {
- FrameInfoIndexEnum start;
- FrameInfoIndexEnum end;
+ FrameInfoIndex start;
+ FrameInfoIndex end;
};
static const Comparison COMPARISONS[] = {
@@ -91,15 +91,15 @@
}
void JankTracker::addFrame(const FrameInfo& frame) {
- using namespace FrameInfoIndex;
mTotalFrameCount++;
// Fast-path for jank-free frames
- int64_t totalDuration = frame[kFrameCompleted] - frame[kIntendedVsync];
+ int64_t totalDuration =
+ frame[FrameInfoIndex::kFrameCompleted] - frame[FrameInfoIndex::kIntendedVsync];
if (CC_LIKELY(totalDuration < mFrameInterval)) {
return;
}
- if (frame[kFlags] & EXEMPT_FRAMES_FLAGS) {
+ if (frame[FrameInfoIndex::kFlags] & EXEMPT_FRAMES_FLAGS) {
return;
}
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 3f79cef..b62af3b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -753,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);
@@ -862,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() &&
@@ -924,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);
@@ -1061,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);
@@ -1233,7 +1233,7 @@
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshIndexedQuads(&mesh[0], quadCount)
.setFillClear()
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
.setModelViewOffsetRect(0, 0, currentSnapshot()->getClipRect())
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1437,7 +1437,7 @@
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshIndexedQuads(&rectangleVertices[0], rectangleVertices.size() / 4)
.setFillBlack()
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), Matrix4::identity(), false)
.setModelViewOffsetRect(0, 0, scissorBox)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -1981,19 +1981,6 @@
}
void OpenGLRenderer::drawAlphaBitmap(Texture* texture, const SkPaint* paint) {
- if (USE_GLOPS) {
- Glop glop;
- GlopBuilder aBuilder(mRenderState, mCaches, &glop);
- aBuilder.setMeshTexturedUnitQuad(texture->uvMapper, true)
- .setFillTexturePaint(*texture, true, paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
- .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .build();
- renderGlop(glop);
- return;
- }
-
float x = 0;
float y = 0;
@@ -2061,6 +2048,20 @@
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, paint);
} else {
@@ -2376,7 +2377,7 @@
bool shadowInterp = displayFlags & kVertexBuffer_ShadowInterp;
aBuilder.setMeshVertexBuffer(vertexBuffer, shadowInterp)
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), fudgeOffset)
.setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -2692,9 +2693,9 @@
if (USE_GLOPS) {
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
- aBuilder.setMeshTexturedUnitQuad(nullptr, true)
+ aBuilder.setMeshTexturedUnitQuad(nullptr)
.setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
.setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -3048,45 +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 = 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;
- }
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRectsDebug(layer->region);
#endif
@@ -3139,9 +3153,9 @@
if (USE_GLOPS) {
Glop glop;
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
- aBuilder.setMeshTexturedUnitQuad(nullptr, true)
+ aBuilder.setMeshTexturedUnitQuad(nullptr)
.setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
.setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -3303,7 +3317,7 @@
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshIndexedQuads(&mesh[0], count / 4)
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
.setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -3349,7 +3363,7 @@
GlopBuilder aBuilder(mRenderState, mCaches, &glop);
aBuilder.setMeshUnitQuad()
.setFillPaint(*paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), transform, false)
+ .setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
.setModelViewMapUnitToRect(Rect(left, top, right, bottom))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
@@ -3381,19 +3395,6 @@
}
void OpenGLRenderer::drawTextureRect(Texture* texture, const SkPaint* paint) {
- if (USE_GLOPS) {
- Glop glop;
- GlopBuilder aBuilder(mRenderState, mCaches, &glop);
- aBuilder.setMeshTexturedUnitQuad(texture->uvMapper, false)
- .setFillTexturePaint(*texture, false, paint, currentSnapshot()->alpha)
- .setTransformClip(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
- .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
- .setRoundRectClipState(currentSnapshot()->roundRectClipState)
- .build();
- renderGlop(glop);
- return;
- }
-
texture->setWrap(GL_CLAMP_TO_EDGE, true);
GLvoid* vertices = (GLvoid*) nullptr;
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/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/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 b64dbdc..192bf81 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -253,7 +253,6 @@
glUniform1f(fill.program->getUniform("roundRectRadius"),
roundedOutRadius);
}
-
// --------------------------------
// ---------- Mesh setup ----------
// --------------------------------
@@ -269,16 +268,16 @@
// glop.fill.texture always takes slot 0, shader samplers increment from there
mCaches->textureState().activateTexture(0);
- if (glop.fill.textureClamp != GL_INVALID_ENUM) {
- glop.fill.texture->setWrap(glop.fill.textureClamp, true);
+ if (glop.fill.texture.clamp != GL_INVALID_ENUM) {
+ glop.fill.texture.texture->setWrap(glop.fill.texture.clamp, true);
}
- if (glop.fill.textureFilter != GL_INVALID_ENUM) {
- glop.fill.texture->setFilter(glop.fill.textureFilter, true);
+ if (glop.fill.texture.filter != GL_INVALID_ENUM) {
+ glop.fill.texture.texture->setFilter(glop.fill.texture.filter, true);
}
- mCaches->textureState().bindTexture(fill.texture->id);
+ mCaches->textureState().bindTexture(fill.texture.texture->id);
meshState().enableTexCoordsVertexArray();
- meshState().bindTexCoordsVertexPointer(force, mesh.texCoordOffset);
+ meshState().bindTexCoordsVertexPointer(force, mesh.texCoordOffset, mesh.stride);
} else {
meshState().disableTexCoordsVertexArray();
}
@@ -313,8 +312,13 @@
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;
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 80c60d9..fcf6eb2 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -399,7 +399,7 @@
continue;
}
fprintf(file, "\n");
- for (int i = 0; i < FrameInfoIndex::kNumIndexes; i++) {
+ for (int i = 0; i < static_cast<int>(FrameInfoIndex::kNumIndexes); i++) {
fprintf(file, "%" PRId64 ",", frame[i]);
}
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 679a00f..f48ee41 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -114,7 +114,8 @@
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
- mRenderThread->timeLord().vsyncReceived(mFrameInfo[FrameInfoIndex::kVsync]);
+ int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::kVsync)];
+ mRenderThread->timeLord().vsyncReceived(vsync);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 3a31db0..0fa2f23 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,10 +52,11 @@
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
-HWUI_ENUM(DumpFlags,
+enum class DumpFlags {
kFrameStats = 1 << 0,
kReset = 1 << 1,
-);
+};
+MAKE_FLAGS_ENUM(DumpFlags)
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index bffbbef..0d1e63e 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -89,8 +89,6 @@
android::uirenderer::Rect DUMMY;
- std::vector< sp<RenderNode> > cards;
-
DisplayListRenderer* renderer = startRecording(rootNode);
animation.createContent(width, height, renderer);
endRecording(renderer, rootNode);
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index b93f720..49d364e7 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -35,12 +35,12 @@
static_assert(std::is_standard_layout<Type>::value, \
#Type " must have standard layout")
-#define HWUI_ENUM(name, ...) \
- namespace name { \
- enum _##name { \
- __VA_ARGS__ \
- }; \
- } \
- typedef enum name::_##name name##Enum
+#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/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/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 99%
rename from core/java/android/midi/MidiDeviceServer.java
rename to media/java/android/media/midi/MidiDeviceServer.java
index 4a1995f..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;
diff --git a/core/java/android/midi/MidiInputPort.java b/media/java/android/media/midi/MidiInputPort.java
similarity index 98%
rename from core/java/android/midi/MidiInputPort.java
rename to media/java/android/media/midi/MidiInputPort.java
index 735c68a..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;
diff --git a/core/java/android/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
similarity index 79%
rename from core/java/android/midi/MidiManager.java
rename to media/java/android/media/midi/MidiManager.java
index 3a0b064..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,18 +51,38 @@
// 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);
+ }
}
}
@@ -74,7 +95,7 @@
*
* @param device a {@link MidiDeviceInfo} for the newly added device
*/
- void onDeviceAdded(MidiDeviceInfo device) {
+ public void onDeviceAdded(MidiDeviceInfo device) {
}
/**
@@ -82,7 +103,7 @@
*
* @param device a {@link MidiDeviceInfo} for the removed device
*/
- void onDeviceRemoved(MidiDeviceInfo device) {
+ public void onDeviceRemoved(MidiDeviceInfo device) {
}
}
@@ -98,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) {
@@ -143,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 98%
rename from core/java/android/midi/MidiOutputPort.java
rename to media/java/android/media/midi/MidiOutputPort.java
index b9512fd..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;
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 93%
rename from core/java/android/midi/MidiReceiver.java
rename to media/java/android/media/midi/MidiReceiver.java
index 16c9bbb..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
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/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/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index c34be22..e4b543b 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -108,4 +108,5 @@
<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 3f8c1da..c54656e 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -108,4 +108,5 @@
<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 347edb4..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>
@@ -103,17 +103,18 @@
<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>
+ <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>
+ <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 c03fc61..5dcb82c 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -108,4 +108,5 @@
<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 97fbc0e..2b13a07 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -108,4 +108,5 @@
<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 7310450..e675c7a 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -108,4 +108,5 @@
<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 7e83314..e1fa6f9 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -112,4 +112,5 @@
<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 f99479f..77e8ce3 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -108,4 +108,5 @@
<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 bfab539..e21961d 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -108,4 +108,5 @@
<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 5c98566..7084c84 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -108,4 +108,5 @@
<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 859eee9..ee5da13 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -108,4 +108,5 @@
<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 859eee9..ee5da13 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 0009935..b34dd05 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -108,4 +108,5 @@
<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 7b1078f..be3c113 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -108,4 +108,5 @@
<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 0d3abb4..402fc14 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -108,4 +108,5 @@
<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 a9c0f8c..86850bb 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -108,4 +108,5 @@
<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 ac819ef..b297f09 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -108,4 +108,5 @@
<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 a69ba60..68f7016 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -108,4 +108,5 @@
<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 c44a9dc..2c24f7a 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -108,4 +108,5 @@
<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 f866edb..77a2d06 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -108,4 +108,5 @@
<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 8410848..8e8f5c5 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -108,4 +108,5 @@
<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 ad432f7..0cd65b8 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -108,4 +108,5 @@
<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 abad969..71410c5 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -110,4 +110,5 @@
<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 34f189e..dd43dba 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -108,4 +108,5 @@
<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 f0575c1..e56642a 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -108,4 +108,5 @@
<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 1b0d6ae..29a56ef 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -108,4 +108,5 @@
<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 54aea26..5741cd0 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -108,4 +108,5 @@
<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 30ad3d7..c5c476c 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -108,4 +108,5 @@
<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 edacb2f..a856ccb 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -112,4 +112,5 @@
<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 eda6217..5c76034 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -108,4 +108,5 @@
<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 b2d776e..e9c77fd 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -108,4 +108,5 @@
<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 92646f2..85443f6 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -108,4 +108,5 @@
<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 1bfc27d..be72fd6 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -108,4 +108,5 @@
<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 795b666..cfa1ac0 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 6d849d2..1ef0c19 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -108,4 +108,5 @@
<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 f827ff3..430c19a 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -108,4 +108,5 @@
<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 8b39e57..17c1c5b 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -108,4 +108,5 @@
<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 053d3bf..6d7dcc7 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -112,4 +112,5 @@
<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 06bdebb..e1da889 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -110,4 +110,5 @@
<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 29223af..717671b 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -108,4 +108,5 @@
<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 ba55f0c6..f39a6b7 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 3df10db..2f24901 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -108,4 +108,5 @@
<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 b906bfc..a86bf60 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 265d61d..3d4dee4 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -108,4 +108,5 @@
<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 ae46e8b..4432ceb 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -108,4 +108,5 @@
<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 695e759..efc25cf 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -108,4 +108,5 @@
<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 66817ad..7f6843a 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -108,4 +108,5 @@
<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 36784fe..3a8d91c 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -108,4 +108,5 @@
<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 dd7f185..b47b76e 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -112,4 +112,5 @@
<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 117a76c..9068898 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -108,4 +108,5 @@
<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 06b4dbb..690b693 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -108,4 +108,5 @@
<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 83da487..1e6fc00 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -110,4 +110,5 @@
<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 3137590..48fd4f6 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -112,4 +112,5 @@
<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 3ec2b05..740b0ea 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -108,4 +108,5 @@
<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 a58ea46..2fbe838 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -112,4 +112,5 @@
<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 4a44ae4..a79d99a 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -112,4 +112,5 @@
<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 22538b1..b7c439b 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -110,4 +110,5 @@
<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 85b2964..75adc2c 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -108,4 +108,5 @@
<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 9195740..886c22e 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -108,4 +108,5 @@
<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 1950d33..89c1480 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 1b91f3ef6..2f51742 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -108,4 +108,5 @@
<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 397e887..6d0d026 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -108,4 +108,5 @@
<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 35cd62a..8125efe 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -108,4 +108,5 @@
<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 02b3613..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>
@@ -108,4 +108,5 @@
<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 2d0a0ef..9e52283 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -112,4 +112,5 @@
<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 081f45b..5cd54c0 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -108,4 +108,5 @@
<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 e9e7e6b..a6852a7 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -108,4 +108,5 @@
<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 45fe1e7..5727900 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -108,4 +108,5 @@
<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 6d5cdb2..a93b54b 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -108,4 +108,5 @@
<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 1479da3..55a6a5e 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -108,4 +108,5 @@
<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 c943c3a..66c665f 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -108,4 +108,5 @@
<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 0d2b8da..be8900a 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -108,4 +108,5 @@
<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/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/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/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 45f4290..2d458fa 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index aac7a2f..3248d7a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 447196a..f933a12 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -92,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>
@@ -147,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>
@@ -205,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>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a058c39..6212b3f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 8805acf..a6fc71f 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 1b9987c..d48be7e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c5ee2fb..8c7428b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -90,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>
@@ -205,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>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 11f1640..ff21bc9 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4bf3076..a5685ee 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index d5a7b2b..ec61344 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a7c929b..c6cc776 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a7c929b..c6cc776 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index aeef5b7..a04779b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 39e83a4..a9103a8 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index d58bc52..4f891e3 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 1753575..3697b05 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index a704494..602d1c2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4480bda7..4224e30 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 49dd20a..b064d0e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4b3f42a..5af507b 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 350a50f..9b3d62e 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -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>
@@ -373,7 +372,7 @@
<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">"Rexeitar"</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 73ec483..65ee915 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -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>
@@ -373,5 +372,5 @@
<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>
+ <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 be21b3c..113a0cf 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -89,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>
@@ -202,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>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 5d6a599..bdad948 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index abef9a0..6cc1292 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 451983d..26cad0c 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index c616ab3..c7afebc 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a9a7297..7f5224e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 70de38d..5090ca7 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -90,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 +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>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1b44396..d106f91 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 1bf9099..cb8c609 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 805fca6..a6077a1 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 52dd68c..7e9eb9a 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 6df8655..85fefec 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 1266898..d6f8219 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -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,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 d2a35cd..0029d67 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index ac39b3c..cc3d0cc0 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -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,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 1b523a2..b83f88f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -90,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>
@@ -203,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>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 4461006..cc2702b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -89,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>
@@ -202,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>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index d65bf65..a5bb833 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 467453e..cc2188b 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -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>
@@ -373,5 +372,5 @@
<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>
+ <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 a02ccf2..fd16012 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -86,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>
@@ -199,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>
@@ -367,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 9399957..afaa65d 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -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,9 +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_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_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 72783a5..d0f3213 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 6043929..b572ba2 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9ea954e..b78723c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 38b4d56..45e338a 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -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>
@@ -373,5 +372,5 @@
<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>
+ <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 be46153..4006618 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 5e6c632..1b9e1d4 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -90,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>
@@ -203,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>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b9977ff..4cdb511 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 90913c9..461ac26 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2b815ab..fbaf763 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -89,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>
@@ -202,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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8904be2..b57ccb3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -90,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>
@@ -205,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>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index f8d2293..e6ec65f 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -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>
@@ -373,5 +372,5 @@
<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>
+ <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 ddb45b4a..eba3977 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -90,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>
@@ -205,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>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 24b92c4..65d684b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -90,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>
@@ -203,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>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 552b377..fca2a8a 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -89,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>
@@ -202,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>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c8587c0..020e777 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d933224..ca4baee 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index c9a7459..b716bda 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 481acc3..97ea24c 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2aab5ff..286d390 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 5a36fb2..95d16d0 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 0ae1e14..10ca6fe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -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,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 ccecdba..ef6c28d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -90,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 +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,9 +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_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_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 51180fb..ec66ac4 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -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,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 2e1f94f..439adcf 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d3e7a14..759a4fb 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -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>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 31f0a4dd..1c39be4 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -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,14 +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>
- <!-- no translation found for volumeui_prompt_message (918680947433389110) -->
- <skip />
- <!-- no translation found for volumeui_prompt_allow (7954396902482228786) -->
- <skip />
- <!-- no translation found for volumeui_prompt_deny (5720663643411696731) -->
- <skip />
- <!-- no translation found for volumeui_notification_title (4906770126345910955) -->
- <skip />
- <!-- no translation found for volumeui_notification_text (1826889705095768656) -->
- <skip />
+ <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 a352a23..a4f4f45 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -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,9 +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_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_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 7cef5aa..b38991d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -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,9 +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_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>
+ <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 7bb54d6..7f3ac02 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -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>
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/strings.xml b/packages/SystemUI/res/values/strings.xml
index d8b6a82..1b1b525 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -430,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] -->
@@ -554,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] -->
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/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/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/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 8048a48..5e3ec3f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -44,6 +44,7 @@
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;
@@ -114,6 +115,7 @@
if (LOGD) Log.d(TAG, "Registering volume controller");
mAudioManager.setVolumeController(mVolumeController);
mMediaSessionManager.setRemoteVolumeController(mRemoteVolumeController);
+ DndTile.setVisible(mContext, false);
} else {
if (LOGD) Log.d(TAG, "Unregistering volume controller");
mAudioManager.setVolumeController(null);
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/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index e7487aa..417bfe2 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -938,6 +938,8 @@
long mDev;
long mContext;
+ private boolean mDestroyed = false;
+
@SuppressWarnings({"FieldCanBeLocal"})
MessageThread mMessageThread;
@@ -1382,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
@@ -1390,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/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/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 895a5c3..c189fea 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -228,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)
@@ -237,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
@@ -462,12 +473,18 @@
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
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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4504ce4..966dc88 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7782,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();
}
@@ -7895,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;
@@ -7909,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)) {
@@ -8043,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);
@@ -8296,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 {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index c0d2502..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);
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 02c8cce..473f5db 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1182,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);
}
@@ -1426,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);
@@ -1435,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);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 09dc477..5f0ad9f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -46,7 +46,6 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.text.TextUtils;
-import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -832,6 +831,24 @@
}
}
+ private void setDisplayOffsetsInternal(int displayId, int x, int y) {
+ synchronized (mSyncRoot) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display == null) {
+ return;
+ }
+ if (display.getDisplayOffsetXLocked() != x
+ || display.getDisplayOffsetYLocked() != y) {
+ if (DEBUG) {
+ Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
+ + x + ", " + y + ")");
+ }
+ display.setDisplayOffsetsLocked(x, y);
+ scheduleTraversalLocked(false);
+ }
+ }
+ }
+
private void clearViewportsLocked() {
mDefaultViewport.valid = false;
mExternalTouchViewport.valid = false;
@@ -1513,5 +1530,10 @@
float requestedRefreshRate, boolean inTraversal) {
setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, inTraversal);
}
+
+ @Override
+ public void setDisplayOffsets(int displayId, int x, int y) {
+ setDisplayOffsetsInternal(displayId, x, y);
+ }
}
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 6c57eec..3bb7818 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -76,6 +76,10 @@
// The pending requested refresh rate. 0 if no request is pending.
private float mRequestedRefreshRate;
+ // The display offsets to apply to the display projection.
+ private int mDisplayOffsetX;
+ private int mDisplayOffsetY;
+
// Temporary rectangle used when needed.
private final Rect mTempLayerStackRect = new Rect();
private final Rect mTempDisplayRect = new Rect();
@@ -313,6 +317,10 @@
mTempDisplayRect.set(displayRectLeft, displayRectTop,
displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
+ mTempDisplayRect.left += mDisplayOffsetX;
+ mTempDisplayRect.right += mDisplayOffsetX;
+ mTempDisplayRect.top += mDisplayOffsetY;
+ mTempDisplayRect.bottom += mDisplayOffsetY;
device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
}
@@ -356,10 +364,34 @@
return mRequestedRefreshRate;
}
+ /**
+ * Gets the burn-in offset in X.
+ */
+ public int getDisplayOffsetXLocked() {
+ return mDisplayOffsetX;
+ }
+
+ /**
+ * Gets the burn-in offset in Y.
+ */
+ public int getDisplayOffsetYLocked() {
+ return mDisplayOffsetY;
+ }
+
+ /**
+ * Sets the burn-in offsets.
+ */
+ public void setDisplayOffsetsLocked(int x, int y) {
+ mDisplayOffsetX = x;
+ mDisplayOffsetY = y;
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println("mDisplayId=" + mDisplayId);
pw.println("mLayerStack=" + mLayerStack);
pw.println("mHasContent=" + mHasContent);
+ pw.println("mRequestedRefreshRate=" + mRequestedRefreshRate);
+ pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
mPrimaryDisplayDevice.getNameLocked() : "null"));
pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
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 06c154e..a5efc83 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -338,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
@@ -347,13 +348,18 @@
}
}
- private void enforceSystemUiPermission(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;
+ 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);
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/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
new file mode 100644
index 0000000..b8a3155
--- /dev/null
+++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
@@ -0,0 +1,217 @@
+/*
+ * 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.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.SystemClock;
+import android.view.Display;
+
+import com.android.server.LocalServices;
+
+import java.io.PrintWriter;
+import java.util.concurrent.TimeUnit;
+
+public class BurnInProtectionHelper implements DisplayManager.DisplayListener {
+ private static final String TAG = "BurnInProtection";
+
+ // Default value when max burnin radius is not set.
+ public static final int BURN_IN_RADIUS_MAX_DEFAULT = -1;
+
+ private static final long BURNIN_PROTECTION_WAKEUP_INTERVAL_MS = TimeUnit.MINUTES.toMillis(1);
+ private static final long BURNIN_PROTECTION_MINIMAL_INTERVAL_MS = TimeUnit.SECONDS.toMillis(10);
+
+ private static final String ACTION_BURN_IN_PROTECTION =
+ "android.internal.policy.action.BURN_IN_PROTECTION";
+
+ private static final int BURN_IN_SHIFT_STEP = 2;
+
+ private boolean mBurnInProtectionActive;
+
+ private final int mMinHorizontalBurnInOffset;
+ private final int mMaxHorizontalBurnInOffset;
+ private final int mMinVerticalBurnInOffset;
+ private final int mMaxVerticalBurnInOffset;
+
+ private final int mBurnInRadiusMaxSquared;
+
+ private int mLastBurnInXOffset = 0;
+ /* 1 means increasing, -1 means decreasing */
+ private int mXOffsetDirection = 1;
+ private int mLastBurnInYOffset = 0;
+ /* 1 means increasing, -1 means decreasing */
+ private int mYOffsetDirection = 1;
+
+ private final AlarmManager mAlarmManager;
+ private final PendingIntent mBurnInProtectionIntent;
+ private final DisplayManagerInternal mDisplayManagerInternal;
+ private final Display mDisplay;
+
+ private BroadcastReceiver mBurnInProtectionReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateBurnInProtection();
+ }
+ };
+
+ public BurnInProtectionHelper(Context context) {
+ final Resources resources = context.getResources();
+ mMinHorizontalBurnInOffset = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
+ mMaxHorizontalBurnInOffset = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
+ mMinVerticalBurnInOffset = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
+ mMaxVerticalBurnInOffset = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
+ int burnInRadiusMax = resources.getInteger(
+ com.android.internal.R.integer.config_burnInProtectionMaxRadius);
+ if (burnInRadiusMax != BURN_IN_RADIUS_MAX_DEFAULT) {
+ mBurnInRadiusMaxSquared = burnInRadiusMax * burnInRadiusMax;
+ } else {
+ mBurnInRadiusMaxSquared = BURN_IN_RADIUS_MAX_DEFAULT;
+ }
+
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ context.registerReceiver(mBurnInProtectionReceiver,
+ new IntentFilter(ACTION_BURN_IN_PROTECTION));
+ Intent intent = new Intent(ACTION_BURN_IN_PROTECTION);
+ intent.setPackage(context.getPackageName());
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mBurnInProtectionIntent = PendingIntent.getBroadcast(context, 0,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ DisplayManager displayManager =
+ (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ displayManager.registerDisplayListener(this, null /* handler */);
+ }
+
+ public void startBurnInProtection() {
+ if (!mBurnInProtectionActive) {
+ mBurnInProtectionActive = true;
+ updateBurnInProtection();
+ }
+ }
+
+ private void updateBurnInProtection() {
+ if (mBurnInProtectionActive) {
+ adjustOffsets();
+ mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(),
+ mLastBurnInXOffset, mLastBurnInYOffset);
+ // Next adjustment at least ten seconds in the future.
+ long next = SystemClock.elapsedRealtime() + BURNIN_PROTECTION_MINIMAL_INTERVAL_MS;
+ // And aligned to the minute.
+ next = next - next % BURNIN_PROTECTION_WAKEUP_INTERVAL_MS
+ + BURNIN_PROTECTION_WAKEUP_INTERVAL_MS;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mBurnInProtectionIntent);
+ } else {
+ mAlarmManager.cancel(mBurnInProtectionIntent);
+ mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), 0, 0);
+ }
+ }
+
+ public void cancelBurnInProtection() {
+ if (mBurnInProtectionActive) {
+ mBurnInProtectionActive = false;
+ updateBurnInProtection();
+ }
+ }
+
+ /**
+ * Gently shifts current burn-in offsets, minimizing the change for the user.
+ *
+ * Shifts are applied in following fashion:
+ * 1) shift horizontally from minimum to the maximum;
+ * 2) shift vertically by one from minimum to the maximum;
+ * 3) shift horizontally from maximum to the minimum;
+ * 4) shift vertically by one from minimum to the maximum.
+ * 5) if you reach the maximum vertically, start shifting back by one from maximum to minimum.
+ *
+ * On top of that, stay within specified radius. If the shift distance from the center is
+ * higher than the radius, skip these values and go the next position that is within the radius.
+ */
+ private void adjustOffsets() {
+ do {
+ // By default, let's just shift the X offset.
+ final int xChange = mXOffsetDirection * BURN_IN_SHIFT_STEP;
+ mLastBurnInXOffset += xChange;
+ if (mLastBurnInXOffset > mMaxHorizontalBurnInOffset
+ || mLastBurnInXOffset < mMinHorizontalBurnInOffset) {
+ // Whoops, we went too far horizontally. Let's retract..
+ mLastBurnInXOffset -= xChange;
+ // change horizontal direction..
+ mXOffsetDirection *= -1;
+ // and let's shift the Y offset.
+ final int yChange = mYOffsetDirection * BURN_IN_SHIFT_STEP;
+ mLastBurnInYOffset += yChange;
+ if (mLastBurnInYOffset > mMaxVerticalBurnInOffset
+ || mLastBurnInYOffset < mMinVerticalBurnInOffset) {
+ // Whoops, we went to far vertically. Let's retract..
+ mLastBurnInYOffset -= yChange;
+ // and change vertical direction.
+ mYOffsetDirection *= -1;
+ }
+ }
+ // If we are outside of the radius, let's try again.
+ } while (mBurnInRadiusMaxSquared != BURN_IN_RADIUS_MAX_DEFAULT
+ && mLastBurnInXOffset * mLastBurnInXOffset + mLastBurnInYOffset * mLastBurnInYOffset
+ > mBurnInRadiusMaxSquared);
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + TAG);
+ prefix += " ";
+ pw.println(prefix + "mBurnInProtectionActive=" + mBurnInProtectionActive);
+ pw.println(prefix + "mHorizontalBurnInOffsetsBounds=(" + mMinHorizontalBurnInOffset + ", "
+ + mMaxHorizontalBurnInOffset + ")");
+ pw.println(prefix + "mVerticalBurnInOffsetsBounds=(" + mMinVerticalBurnInOffset + ", "
+ + mMaxVerticalBurnInOffset + ")");
+ pw.println(prefix + "mBurnInRadiusMaxSquared=" + mBurnInRadiusMaxSquared);
+ pw.println(prefix + "mLastBurnInOffset=(" + mLastBurnInXOffset + ", "
+ + mLastBurnInYOffset + ")");
+ pw.println(prefix + "mOfsetChangeDirections=(" + mXOffsetDirection + ", "
+ + mYOffsetDirection + ")");
+ }
+
+ @Override
+ public void onDisplayAdded(int i) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int i) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == mDisplay.getDisplayId()) {
+ if (mDisplay.getState() == Display.STATE_DOZE
+ || mDisplay.getState() == Display.STATE_DOZE_SUSPEND) {
+ startBurnInProtection();
+ } else {
+ cancelBurnInProtection();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b90d263..c414072 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1,4 +1,5 @@
/*
+ * 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.
@@ -74,6 +75,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 +105,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;
@@ -253,6 +257,7 @@
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
SearchManager mSearchManager;
AccessibilityManager mAccessibilityManager;
+ BurnInProtectionHelper mBurnInProtectionHelper;
// Vibrator pattern for haptic feedback of a long press.
long[] mLongPressVibePattern;
@@ -724,12 +729,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,
@@ -1187,6 +1187,10 @@
mWindowManagerFuncs = windowManagerFuncs;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
+ if (context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableBurnInProtection)){
+ mBurnInProtectionHelper = new BurnInProtectionHelper(context);
+ }
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
@@ -1359,6 +1363,9 @@
if (!mPowerManager.isInteractive()) {
goingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
}
+
+ mWindowManagerInternal.registerAppTransitionListener(
+ mStatusBarController.getAppTransitionListener());
}
/**
@@ -6456,5 +6463,8 @@
if (mOrientationListener != null) {
mOrientationListener.dump(pw, prefix);
}
+ if (mBurnInProtectionHelper != null) {
+ mBurnInProtectionHelper.dump(prefix, pw);
+ }
}
}
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/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 2afeaab..ef70895 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,16 +17,13 @@
package com.android.server.wm;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Debug;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
-import android.os.UserHandle;
-import android.util.Log;
import android.util.Slog;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
@@ -47,7 +44,9 @@
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;
@@ -185,6 +184,8 @@
private int mCurrentUserId = 0;
+ private final ArrayList<AppTransitionListener> mListeners = new ArrayList<>();
+
AppTransition(Context context, Handler h) {
mContext = context;
mH = h;
@@ -291,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() {
@@ -309,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) {
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/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/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/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index abf8412..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 */
@@ -158,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,
@@ -177,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,
@@ -601,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 e238d30..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;
@@ -189,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;
@@ -327,6 +329,7 @@
final boolean mHaveInputMethods;
final boolean mHasPermanentDpad;
+ final long mDrawLockTimeoutMillis;
final boolean mAllowBootMessages;
@@ -680,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;
@@ -779,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,
@@ -817,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();
@@ -855,6 +889,7 @@
mScreenFrozenLock.setReferenceCounted(false);
mAppTransition = new AppTransition(context, mH);
+ mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);
mActivityManager = ActivityManagerNative.getDefault();
mBatteryStats = BatteryStatsService.getService();
@@ -2930,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,
@@ -4272,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(
@@ -5045,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);
@@ -5055,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
@@ -5085,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.
@@ -7904,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:
@@ -8873,7 +8962,6 @@
if (mSkipAppTransitionAnimation) {
transit = AppTransition.TRANSIT_UNSET;
}
- mAppTransition.goodToGo();
mStartingIconInTransition = false;
mSkipAppTransitionAnimation = false;
@@ -9026,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();
}
}
@@ -9048,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;
@@ -9084,6 +9174,7 @@
if (wtoken.startingWindow != null && !wtoken.startingWindow.mExiting) {
scheduleRemoveStartingWindowLocked(wtoken);
}
+ mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
if (animLp != null) {
int layer = -1;
@@ -9168,6 +9259,7 @@
}
}
+ mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator);
mAppTransition.postAnimationCallback();
mAppTransition.clear();
@@ -9750,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
@@ -9924,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;
@@ -11586,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 d58b2b0..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();
@@ -1642,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 a78bab45..89ed5b7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -238,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? */
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 770da5b..6dc54ce 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4053,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) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 009d25d..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;
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 396ed38..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;
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 54525ad..5c6d870 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -132,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):
@@ -150,12 +154,13 @@
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(f):
+def _parse_stream(f, clazz_cb=None):
line = 0
api = {}
pkg = None
@@ -163,7 +168,7 @@
blame = None
re_blame = re.compile("^([a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
- for raw in f.readlines():
+ for raw in f:
line += 1
raw = raw.rstrip()
match = re_blame.match(raw)
@@ -176,8 +181,13 @@
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)
- api[clazz.fullname] = clazz
+ if not clazz_cb:
+ api[clazz.fullname] = clazz
elif raw.startswith(" ctor"):
clazz.ctors.append(Method(clazz, line, raw, blame))
elif raw.startswith(" method"):
@@ -185,19 +195,16 @@
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
-def parse_api_file(fn):
- with open(fn) as f:
- return parse_api(f)
-
-
class Failure():
def __init__(self, sig, clazz, detail, error, rule, msg):
self.sig = sig
- self.clazz = clazz
- self.detail = detail
self.error = error
self.rule = rule
self.msg = msg
@@ -644,7 +651,7 @@
warn(clazz, m, "FW6", "Method argument type violates package layering")
-def verify_boolean(clazz, api):
+def verify_boolean(clazz):
"""Verifies that boolean accessors are named correctly.
For example, hasFoo() and setHasFoo()."""
@@ -758,7 +765,7 @@
if not clazz.name.endswith("Manager"): return
for c in clazz.ctors:
- error(clazz, c, None, "Managers must always be obtained from Context")
+ error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors")
def verify_boxed(clazz):
@@ -809,7 +816,7 @@
if "deprecated" in m.split: continue
overloads[m.name].append(m)
- for name, methods in overloads.iteritems():
+ for name, methods in overloads.items():
if len(methods) <= 1: continue
# Look for arguments common across all overloads
@@ -844,35 +851,26 @@
"""Verifies that methods adding listener/callback have overload
for specifying delivery thread."""
- # Ignore UI components which deliver things on main thread
+ # Ignore UI packages which assume main thread
skip = [
- "android.animation",
- "android.view",
- "android.graphics",
- "android.transition",
- "android.widget",
- "android.webkit",
+ "animation",
+ "view",
+ "graphics",
+ "transition",
+ "widget",
+ "webkit",
]
for s in skip:
- if clazz.fullname.startswith(s): return
- if clazz.extends and clazz.extends.startswith(s): return
+ if s in clazz.pkg.name_path: return
+ if s in clazz.extends_path: return
- skip = [
- "android.app.ActionBar",
- "android.app.AlertDialog",
- "android.app.AlertDialog.Builder",
- "android.app.Application",
- "android.app.Activity",
- "android.app.Dialog",
- "android.app.Fragment",
- "android.app.FragmentManager",
- "android.app.LoaderManager",
- "android.app.ListActivity",
- "android.app.AlertDialog.Builder"
- "android.content.Loader",
- ]
- for s in skip:
- if clazz.fullname == s or clazz.extends == s: 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)
@@ -945,56 +943,65 @@
error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
-def verify_style(api):
- """Find all style issues in the given API level."""
- global failures
+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)
- 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)
-
+ examine_clazz(api[key])
return failures
@@ -1054,18 +1061,20 @@
if __name__ == "__main__":
- cur = parse_api_file(sys.argv[1])
- cur_fail = verify_style(cur)
+ with open(sys.argv[1]) as f:
+ cur_fail = examine_stream(f)
if len(sys.argv) > 2:
- prev = parse_api_file(sys.argv[2])
- prev_fail = verify_style(prev)
+ 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]
+ """
+ # NOTE: disabled because of memory pressure
# look for compatibility issues
compat_fail = verify_compat(cur, prev)
@@ -1073,7 +1082,7 @@
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):
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/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/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());
}